用Unity解析IEnumerable <t> </t>

时间:2009-12-25 17:26:33

标签: c# dependency-injection unity-container ienumerable

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,所以我可能错过了一些东西。

8 个答案:

答案 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")
                    )
));