Search code examples
dependency-injectioninversion-of-controlautofac

Autofac named registration constructor injection


Does Autofac support specifying the registration name in the components' constructors?

Example: Ninject's NamedAttribute.


Solution

  • You need to use the Autofac.Extras.Attributed package on top to achieve this

    So let's say you have one interface and two classes:

    public interface IHello
    {
        string SayHello();
    }
    
    public class EnglishHello : IHello
    {
        public string SayHello()
        {
            return "Hello";
        }
    }
    
    public class FrenchHello : IHello
    {
        public string SayHello()
        {
            return "Bonjour";
        }
    }
    

    Then you have a consumer class, which in you want to select which instance is injected:

    public class HelloConsumer
    {
        private readonly IHello helloService;
    
        public HelloConsumer([WithKey("EN")] IHello helloService)
        {
            if (helloService == null)
            {
                throw new ArgumentNullException("helloService");
            }
            this.helloService = helloService;
        }
    
        public string SayHello()
        {
            return this.helloService.SayHello();
        }
    }
    

    Registering and resolving:

    ContainerBuilder cb = new ContainerBuilder();
    
    cb.RegisterType<EnglishHello>().Keyed<IHello>("EN");
    cb.RegisterType<FrenchHello>().Keyed<IHello>("FR");
    cb.RegisterType<HelloConsumer>().WithAttributeFilter();
    var container = cb.Build();
    
    var consumer = container.Resolve<HelloConsumer>();
    Console.WriteLine(consumer.SayHello());
    

    Do not forget the AttributeFilter when you register such a consumer, otherwise resolve will fail.

    Another way is to use a lambda instead of attribute.

    cb.Register<HelloConsumer>(ctx => new HelloConsumer(ctx.ResolveKeyed<IHello>("EN")));
    

    I find the second option cleaner since you also avoid to reference autofac assemblies in your project (just to import an attribute), but that part is a personal opinion of course.