Mar*_*ann 37 c# ienumerable dependency-injection unity-container
Unity可以自动解决IEnumerable<T>
吗?
假设我有一个带有这个构造函数的类:
public CoalescingParserSelector(IEnumerable<IParserBuilder> parserBuilders)
Run Code Online (Sandbox Code Playgroud)
我在容器中配置单个IParserBuilder实例:
container.RegisterType<IParserSelector, CoalescingParserSelector>();
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();
Run Code Online (Sandbox Code Playgroud)
我可以在不必实现自定义实现的情况下完成这项工作IEnumerable<IParserBuilder>
吗?
var selector = container.Resolve<IParserSelector>();
Run Code Online (Sandbox Code Playgroud)
到目前为止,我还没有以任何简单的方式表达这一点,但我仍然在提升Unity,所以我可能错过了一些东西.
Mar*_*ann 63
事实证明,这实际上非常简单:
container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
Run Code Online (Sandbox Code Playgroud)
Unity 本身可以理解数组,所以我们只需要将枚举映射到相同类型的数组.
JCa*_*ico 12
@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>()));
Run Code Online (Sandbox Code Playgroud)
为了解决单个实例,您还需要添加默认注册,否则调用Resolve<T>()
将失败.
此代码使默认注册启用单一分辨率:
container.RegisterType<IParserBuilder, HelpParserBuilder>();
IParserBuilder builder = container.Resolve<IParserBuilder>()
Run Code Online (Sandbox Code Playgroud)
小智 7
如果你想一般支持IEnumerable,那么你可以添加这一行:
_container.RegisterType(typeof(IEnumerable<>), new InjectionFactory((IUnityContainer container, Type type, string name) => container.ResolveAll(type.GetGenericArguments().Single())));
Run Code Online (Sandbox Code Playgroud)
这是他的通用版本
container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
Run Code Online (Sandbox Code Playgroud)
我相信你需要使用ResolveAll方法并使用一个显式的InjectionConstructor对象,即:
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();
var injectedBuilders = new InjectionConstructor(container.ResolveAll<IParserBuilder>());
container.RegisterType<IParserSelector, CoalescingParserSelector>(injectedBuilders);
Run Code Online (Sandbox Code Playgroud)
换句话说,我不认为Unity能够自动解析类型的所有实例,并且知道在具有IEnumerable参数的类上使用构造函数注入,而无需在运行时明确声明InjectionConstructor对象.
虽然我也在学习Unity,但这是我的经验(YMMV).
小智 5
该
container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
Run Code Online (Sandbox Code Playgroud)
为我工作时请记住,当您向容器注册IParserBuilder类型时,需要一个唯一的名称,否则它将始终是一个空数组.所以使用
container.RegisterType<IParserBuilder, RealParserBuilder>("UniqueName");
Run Code Online (Sandbox Code Playgroud)