Unity可以自动解决IEnumerable<T>
吗?
假设我有一个带有这个构造函数的类:
public CoalescingParserSelector(IEnumerable<IParserBuilder> parserBuilders)
我在容器中配置了单个IParserBuilder实例:
container.RegisterType<IParserSelector, CoalescingParserSelector>();
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();
我可以在不必实现IEnumerable<IParserBuilder>
的自定义实现的情况下完成这项工作吗?
var selector = container.Resolve<IParserSelector>();
到目前为止,我还没有以任何简单的方式表达这一点,但我仍然在提升Unity,所以我可能错过了一些东西。
答案 0 :(得分:62)
事实证明,这实际上非常简单:
container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
Unity 原生理解数组,因此我们只需要将枚举映射到相同类型的数组。
答案 1 :(得分:11)
@Metro Smurf:你的回答让我走上正轨:Unity无法自动解决IEnumerable<T>
个依赖关系。
我无法编译您的示例,因为RegisterType
方法没有将InjectionConstructor
实例作为参数。
另请注意,ResolveAll
方法仅在您注册了多个具有不同名称的类型时才有效,并且此方法不会返回默认(未命名)注册的实例。 (我完全不同意这种行为btw)。
这对我有用:
container.RegisterType<IParserBuilder, HelpParserBuilder>("HelpParserBuilder");
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>("SomeOtherParserBuilder");
container.RegisterType<IParserSelector, CoalescingParserSelector>();
container.Configure<InjectedMembers>().ConfigureInjectionFor<CoalescingParserSelector>(new InjectionConstructor(container.ResolveAll<IParserBuilder>()));
要解决单个实例,您还需要添加默认注册,否则对Resolve<T>()
的调用将失败。
此代码进行默认注册以启用单一分辨率:
container.RegisterType<IParserBuilder, HelpParserBuilder>();
IParserBuilder builder = container.Resolve<IParserBuilder>()
答案 2 :(得分:6)
我相信您需要使用ResolveAll方法并使用明确的InjectionConstructor对象,即:
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();
var injectedBuilders = new InjectionConstructor(container.ResolveAll<IParserBuilder>());
container.RegisterType<IParserSelector, CoalescingParserSelector>(injectedBuilders);
换句话说,我不认为Unity能够自动解析类型的所有实例,并且知道在具有IEnumerable参数的类上使用构造函数注入,而无需在{{{{}} { 3}}
当然我也在学习Unity,但这是我的经验(YMMV)。
答案 3 :(得分:6)
如果你想一般支持IEnumerable,那么你可以添加这一行:
_container.RegisterType(typeof(IEnumerable<>), new InjectionFactory((IUnityContainer container, Type type, string name) => container.ResolveAll(type.GetGenericArguments().Single())));
这是
的通用版本container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
答案 4 :(得分:5)
在
container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
只为我工作时请记住,当您向容器注册IParserBuilder类型时,需要一个唯一的名称,否则它将始终是一个空数组。所以使用
container.RegisterType<IParserBuilder, RealParserBuilder>("UniqueName");
答案 5 :(得分:4)
截至2010年5月,有本机支持。请查看here。
答案 6 :(得分:4)
我是这样做的
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().
Where(type => typeof(IParserBuilder).IsAssignableFrom(type)),
WithMappings.FromAllInterfaces,
WithName.TypeName,
WithLifetime.Transient);
container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
注册实现IParserBuilder
的所有内容,因此当您添加新内容时,您不需要添加任何其他代码,以便它显示在构建器列表中。
答案 7 :(得分:0)
你可以这样做:
container.RegisterType<IParserBuilder, HelpParserBuilder>("HelpParser");
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>("SomeOtherParser");
container.RegisterType<IParserSelector, CoalescingParserSelector>(
new InjectionConstructor(
new ResolvedArrayParameter<IParserBuilder>(
new ResolvedParameter<IParserBuilder>("HelpParser"),
new ResolvedParameter<IParserBuilder>("SomeOtherParser")
)
));