【问题标题】:Resolving IEnumerable<T> with Unity用 Unity 解析 IEnumerable<T>
【发布时间】:2009-12-25 17:26:33
【问题描述】:

Unity可以自动解析IEnumerable&lt;T&gt;吗?

假设我有一个带有这个构造函数的类:

public CoalescingParserSelector(IEnumerable<IParserBuilder> parserBuilders)

我在容器中配置单独的 IParserBuilder 实例:

container.RegisterType<IParserSelector, CoalescingParserSelector>();
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();

我可以在不必实现IEnumerable&lt;IParserBuilder&gt; 的自定义实现的情况下完成这项工作吗?

var selector = container.Resolve<IParserSelector>();

到目前为止,我还不能用任何简单的方式来表达这一点,但我仍在加强 Unity,所以我可能错过了一些东西。

【问题讨论】:

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


    【解决方案1】:

    如果你想普遍支持IEnumerable,那么你可以添加这一行:

    _container.RegisterType(typeof(IEnumerable<>), new InjectionFactory((IUnityContainer container, Type type, string name) => container.ResolveAll(type.GetGenericArguments().Single())));
    

    这是他的通用版本

    container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
    

    【讨论】:

    • 我喜欢这里简单的一个班轮。在 Unity 添加对 IEnumerable&lt;T&gt; 构造函数注入的原生支持之前,这非常有用。
    【解决方案2】:

    事实证明,这实际上非常简单:

    container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
    

    Unity原生理解数组,所以我们只需要将枚举映射到同类型的数组即可。

    【讨论】:

    • 很好的解决方案!这比所有其他选项都好。
    • 为了填充构造函数注入的 IEnumerable(我希望在这里的答案中看到),请参考以下问题。 stackoverflow.com/questions/6304355/…
    • 太糟糕了,您需要为每种类型添加新的注册。要是有container.RegisterType(GetType(IEnumerable(Of )), GetType(Array(Of )))这样简单的东西就好了
    • 如下所述,如果使用多个实例,您还需要包含唯一名称。否则列表将包含零个项目:container.RegisterType&lt;IParserBuilder, HelpParserBuilder&gt;("HelpParserBuilder");
    • 此解决方案仅在您为注册命名时才有效!即它不会像 OP 在他的问题描述中声明的那样工作!必须改成container.RegisterType&lt;IParserBuilder, HelpParserBuilder&gt;("A");等...
    【解决方案3】:

    @Metro Smurf:你的回答让我走上了正轨:Unity 无法自动解析 IEnumerable&lt;T&gt; 依赖项。

    我无法编译您的示例,因为 RegisterType 方法没有将 InjectionConstructor 实例作为参数。

    另请注意,ResolveAll 方法仅在您注册了具有不同名称的多个类型时才有效,并且此方法不会返回默认(未命名)注册的实例。 (顺便说一句,我完全不同意这种行为)。

    这对我有用:

    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&lt;T&gt;() 的调用将失败。

    此代码使默认注册启用单一分辨率:

    container.RegisterType<IParserBuilder, HelpParserBuilder>();
    IParserBuilder builder = container.Resolve<IParserBuilder>()
    

    【讨论】:

    • +1 也可以,但并不比其他答案好也不差。
    • @Mark:如果您要注册多个实例,则必须提供不同的实例名称。
    【解决方案4】:

    截至 2010 年 5 月,已提供本机支持。看看here

    【讨论】:

    • 虽然支持IEnumerable&lt;T&gt;的分辨率很好,但还不支持构造函数注入。
    【解决方案5】:

    我是这样做的

            container.RegisterTypes(
                AllClasses.FromLoadedAssemblies().
                    Where(type => typeof(IParserBuilder).IsAssignableFrom(type)),
                WithMappings.FromAllInterfaces,
                WithName.TypeName,
                WithLifetime.Transient);
    
            container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
    

    它注册了所有实现 IParserBuilder 的东西,所以当你添加一个新的时,你不需要添加任何其他代码来让它出现在构建器列表中。

    【讨论】:

      【解决方案6】:

      我相信您需要使用ResolveAll 方法并使用明确的InjectionConstructor 对象,即:

      container.RegisterType<IParserBuilder, HelpParserBuilder>();
      container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();
      
      var injectedBuilders = new InjectionConstructor(container.ResolveAll<IParserBuilder>());
      container.RegisterType<IParserSelector, CoalescingParserSelector>(injectedBuilders);
      

      换句话说,我不认为 Unity 能够自动解析一个类型的所有实例,并且知道在没有明确声明 InjectionConstructor 对象 Run Time 的情况下对具有 IEnumerable 参数的类使用构造函数注入。

      当然,我还在学习 Unity,但这是我的经验 (YMMV)。

      【讨论】:

      • +1 不完美,但绝对比我原来的更好。
      • 我对这个解决方案的主要问题是实例是在统一容器设置线程上解决的,这对我没有好处,我需要一组新的注入项目每个解决方案。但是感谢您让我走上正轨。
      【解决方案7】:

      container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
      

      只为我工作请记住,当您向容器注册 IParserBuilder 类型时,需要一个唯一的名称,否则它将始终是一个空数组。所以使用

      container.RegisterType<IParserBuilder, RealParserBuilder>("UniqueName");
      

      【讨论】:

        【解决方案8】:

        你可以这样做:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-04
          • 1970-01-01
          • 2012-09-17
          • 1970-01-01
          相关资源
          最近更新 更多