Autofac命名注册构造函数注入

Joh*_*ant 9 dependency-injection inversion-of-control autofac

Autofac是否支持在组件的构造函数中指定注册名称?

示例:Ninject's NamedAttribute.

cat*_*ier 21

您需要在顶部使用Autofac.Extras.Attributed包来实现此目的

所以假设你有一个接口和两个类:

public interface IHello
{
    string SayHello();
}

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

public class FrenchHello : IHello
{
    public string SayHello()
    {
        return "Bonjour";
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你有一个消费者类,你想要选择注入哪个实例:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

注册和解决:

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());
Run Code Online (Sandbox Code Playgroud)

注册这样的使用者时不要忘记AttributeFilter,否则解决将失败.

另一种方法是使用lambda而不是属性.

cb.Register<HelloConsumer>(ctx => new HelloConsumer(ctx.ResolveKeyed<IHello>("EN")));
Run Code Online (Sandbox Code Playgroud)

我发现第二个选项更清洁,因为你也避免在你的项目中引用autofac程序集(只是为了导入一个属性),但那部分当然是个人意见.

  • `[WithKey]` 属性现已过时。根据此 [文档](https://autofac.org/apidoc/html/9E1F2171.htm) 使用 `[KeyFilter]` 属性。`[ObsoleteAttribute("改为使用核心 Autofac 库中的 Autofac.Features.AttributeFilters.KeyFilterAttribute。")] 公共密封类 WithKeyAttribute : ParameterFilterAttribute` (2认同)