我有三个类声明,如上面的
[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")
我一直认为这不是表演的最佳实践。
答案 0 :(得分:1)
有很多方法可以做你想要的。
最简单的方法是将您的类型注册为命名注册
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");
然后,您将能够使用IPlug
进行所有已命名的IEnumerable<Meta<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>>();