有什么办法可以设置autofac的实例化过程吗?

is there any way to interpose the instantiation process of autofac?

我有三个 class 像上面的声明

 [Plug("hello")]
 public class Plug1 : IPlug{}
 [Plug("hello")]
 public class Plug2 : IPlug{}
 [Plug("world")]
 public class Plug3 : IPlug{}

当我使用 container.Resolve<IEnumerable<IPlug>>() 解析时,我得到了所有实现了 IPlug 接口的实例,但是,我想得到第一个和第二个(或者按世界,实例是由属性 Plug("hello") 标记)。

有什么办法可以实现吗?

我想避免使用

container.Resolve<IEnumerable<IPlug>>()
         .Where(t => t.FirstAttribute<Plug>() != null 
                     && t.FirstAttribute<Plug>().Id == "Hello")

我总觉得这不是性能的最佳实践。

有很多方法可以做你想做的事。

最简单的方法是将您的类型注册为命名注册

builder.RegisterType<Plug1>().As<IPlug>().WithMetadata("plug", "hello");
builder.RegisterType<Plug2>().As<IPlug>().WithMetadata("plug", "hello");
builder.RegisterType<Plug3>().As<IPlug>().WithMetadata("plug", "world");

您还可以使用属性来注册这些类型:

builder.RegisterType<Plug1>()
       .As<IPlug>()
       .WithMetadata("plug", typeof(Plug1).FirstAttribute<Plug>().?Id ?? "Default");

然后您将能够使用 IEnumerable<Meta<IPlug>> 获得所有命名 IPlug 注册:

container.Resolve<IEnumerable<Meta<IPlug>>>()
         .Where(m => m.Metadata["plug"] as String == "hello")
         .Select(m => m.Value);

如果您不想在运行时进行过滤,但在 IoC 根组合期间并且 IEnumerable<IPlug> 将始终解析过滤后的 IEnumerable<IPlug> 那么您可以覆盖 IEnumerable<IPlug> 注册:

builder.Register(c => c.Resolve<IEnumerable<Meta<IPlug>>>()
                       .Where(m => m.Metadata["plug"] as String ==  "hello")
                       .Select(m => m.Value))
       .As<IEnumerable<IPlug>>();