1

Given the following tenant specific registration, when the Letter Factory is used (tenant is correctly identified) the IIndex object always return null when indexed. I have verified that the filtering of the assemblies are correct and each letter is being added to the index at run-time. So my question is how do I troubleshoot this without pulling the source and hooking it up to my project and steeping through it? Are there ways to validate the container after creation, sort of like how AutoMapper does when you configure the mappers?

Thank you, Stephen

FYI:

This is the next iteration from this previously answered question

Container:

mtc.ConfigureTenant("1",
    b =>
    {
        List<Type> letterTypes = typeof(App.BusinessArea.NewBusiness.Letters.LetterBase).Assembly.GetTypes()
            .Where(t => !t.IsAbstract && t.IsSubclassOf(typeof(App.BusinessArea.NewBusiness.Letters.LetterBase)))
            .Where(t => t.GetCustomAttributes(typeof(LetterTypeAttribute), false).Length == 1)
            .ToList();

        foreach (Type letterType in letterTypes)
        {
            LetterTypeAttribute attribute = letterType.GetCustomAttributes<LetterTypeAttribute>()
                .FirstOrDefault();

            if (attribute != null)
            {
                builder.RegisterType(letterType)
                    .Keyed<App.BusinessArea.NewBusiness.Letters.LetterBase>(attribute.LetterId);
            }
        }


        b.RegisterType<App.BusinessArea.NewBusiness.Letters.LetterFactory>()
            .As<App.BusinessArea.NewBusiness.Letters.ILetterFactory>();

        b.RegisterType<App.BusinessArea.NewBusiness.DocumentServices>()
            .As<IDocumentServices>();
    });

mtc.ConfigureTenant("2", 
    b =>
    {
        List<Type> letterTypes = typeof(App.BusinessArea.Claims.Letters.LetterBase).Assembly.GetTypes()
            .Where(t => !t.IsAbstract && t.IsSubclassOf(typeof(App.BusinessArea.Claims.Letters.LetterBase)))
            .Where(t => t.GetCustomAttributes(typeof(LetterTypeAttribute), false).Length == 1)
            .ToList();

        foreach(Type letterType in letterTypes)
        {
            LetterTypeAttribute attribute = letterType.GetCustomAttributes<LetterTypeAttribute>()
                .FirstOrDefault();

            if(attribute != null)
            {
                builder.RegisterType(letterType)
                    .Keyed<App.BusinessArea.Claims.Letters.LetterBase>(attribute.LetterId);
            }
        }

        b.RegisterType<App.BusinessArea.Claims.Letters.LetterFactory>()
            .As<App.BusinessArea.Claims.Letters.ILetterFactory>();

        b.RegisterType<App.BusinessArea.Claims.DocumentService>()
            .As<IDocumentServices>();
    });

Factory per tenant:

public class LetterFactory : ILetterFactory
{
    private readonly IIndex<int, LetterBase> _lettersFactory;

    public LetterFactory(IIndex<int, LetterBase> lettersFactory)
    {
        _lettersFactory = lettersFactory;
    }

    public LetterBase Create(int letterId)
    {
        if (letterId <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(letterId));
        }


        LetterBase letter = null; 
        if(!_lettersFactory.TryGetValue(letterId, out letter))
        {
            string message = $"Could not find a Letter to create for id {letterId}.";
            throw new NotSupportedException(message);        
        }
        return letter;
    }
}
Stephen Patten
  • 6,333
  • 10
  • 50
  • 84
  • 1
    Answer to the nested question that isn't the title question: no, there is no container validation. https://github.com/autofac/Autofac/issues/853 – Travis Illig May 19 '18 at 14:57

1 Answers1

1

I put a simple repro of this together and it works without issue.

Looking closer at your code I think the problem is here:

if (attribute != null)
{
  builder.RegisterType(letterType)
         .Keyed<App.BusinessArea.NewBusiness.Letters.LetterBase>(attribute.LetterId);
}

This is happening inside the multitenant configuration part but you're not registering your letter types with the ContainerBuilder in the lambda (b) - you're using some other ContainerBuilder, likely the one that was used to build the application level container. (This may have been easier to spot for folks perusing the question if the entire container configuration was included here rather than just the multitenant part.)

Try switching to use b.RegisterType... in the lambda.

Travis Illig
  • 23,195
  • 2
  • 62
  • 85