Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac named registration constructor injection

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

Example: Ninject's NamedAttribute.

like image 803
jmercha Avatar asked Jun 02 '14 01:06

jmercha


People also ask

How do I register an Autofac service?

Register by Type var builder = new ContainerBuilder(); builder. RegisterType<ConsoleLogger>(); builder. RegisterType(typeof(ConfigReader)); When using reflection-based components, Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container.

What is Autofac in C#?

Autofac is an addictive Inversion of Control container for . NET Core, ASP.NET Core, . NET 4.5. 1+, Universal Windows apps, and more.

How do I get Autofac containers?

From Visual Studio, you can get it via NuGet. The package name is Autofac. Alternatively, the NuGet package can be downloaded from the GitHub repository (https://github.com/autofac/Autofac/releases).

What is AsImplementedInterfaces?

RegistrationExtensions. AsImplementedInterfaces MethodSpecifies that a type from a scanned assembly is registered as providing all of its implemented interfaces.


1 Answers

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.

like image 174
mrvux Avatar answered Sep 26 '22 00:09

mrvux