代码之家  ›  专栏  ›  技术社区  ›  Julian Lettner

在Ninject中注入接口数组

  •  14
  • Julian Lettner  · 技术社区  · 14 年前

    public interface IFoo { }
    
    
    public class Bar
    {
        public Bar(IFoo[] foos) { }
    }
    
    
    public class MyModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IFoo[]>().ToConstant(new IFoo[0]);
            // ToConstant() is just an example
        }
    }
    
    
    public class Program
    {
        private static void Main(string[] args)
        {
            var kernel = new StandardKernel(new MyModule());
            var bar = kernel.Get<Bar>();
        }
    }
    

    激活IFoo时出错
    没有匹配的绑定可用,并且类型不可自绑定。
    激活路径:
    2) 将依赖项IFoo注入Bar类型构造函数的参数foos

    谢谢你的时间。

    编辑:
    导入过程应用不同类型的过滤器(例如,不同过滤器接口的实现)。过滤规则经常改变,但是太复杂了,不能用纯配置(和主过滤器)来完成。

    我想使添加/编辑过滤器尽可能容易。我拥有的是一个程序集,所有过滤器实现都位于其中。我尝试将每个过滤器接口绑定到以下方法(该方法提供该过滤器类型的每个实现的实例)。基本上,我想避免在添加/删除过滤器类时需要更改Ninject模块。

        private IEnumerable<TInterface> GetInterfaceImplementations<TInterface>(IContext context)
        {
            return GetType().Assembly.GetTypes()
                .Where(t => typeof (TInterface).IsAssignableFrom(t) && IsConcreteClass(t))
                .Select(t => Kernel.Get(t)).Cast<TInterface>();
        }
    

    我对绕过容器DI机制感到有点内疚。这种做法不好吗?做这种事有共同的习惯吗?

    分辨率:
    我按照bsnote的建议使用包装器类。

    3 回复  |  直到 14 年前
        1
  •  7
  •   Ruben Bartelink    14 年前

    这在很大程度上是对@bsnote答案(我已经+1d)的重申,这可能有助于理解它为什么以这种方式工作。

    Ninject(和其他DI/addin框架)有两种不同的功能:

    1. 绑定到服务的单个明确实现的概念( Get )
    2. GetAll ResolveAll 在Ninject中)

    您的示例代码碰巧使用了与上面2.相关联的语法(e、 例如,在MEF中,通常使用 [ImportMany]

    我需要查看示例(查看源代码—它非常简短、干净且易于理解)来找到解决方法。

    然而,正如@bsnote所说的,重构需求的一种方法是将数组包装在容器中,或者使用您请求的对象(即工厂方法或存储库类型构造)

    你也可以解释一下你的真实情况——为什么会有一个裸阵列?当然,在这一切的背后,有一系列的项目需要被封装——这个问题当然不会出现太多?

    编辑:在扩展中有一组扫描示例,我认为这些示例会攻击您正在尝试做的很多东西(在StructureMap之类的东西中,这类东西更集成,这显然有优点和缺点)。

    Bind 每一个。或者,对于CoC,您可以 Module Load() s) 在你的编辑中。

    无论哪种方式,当你有多个注册的地方,你可以很高兴地'要求'一个 T[] IEnumerable<T> 拿到全套。如果您想显式地实现这一点(例如,服务定位器和它所暗示的一切—就像您正在做的那样),您可以使用

        2
  •  11
  •   lys Reid Evans    10 年前

    Ninject支持多重注入,这将解决您的问题。 https://github.com/ninject/ninject/wiki/Multi-injection

    public interface IFoo { }
    public class FooA : IFoo {}
    public class FooB : IFoo {}
    
    public class Bar
    {
        //array injected will contain [ FooA, FooB ] 
        public Bar(IFoo[] foos) { }
    }
    
    public class MyModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IFoo>().To<FooA>();
            Bind<IFoo>().To<FooB>();
            //etc..
        }
    }
    
        3
  •  4
  •   Andrei Sedoi    14 年前

    这对我来说也是个问题。Ninject注入数组的每个项,而不是数组本身,因此应该为数组项的类型定义映射。实际上,不可能将数组作为类型映射到当前版本的Ninject。解决方案是围绕数组创建一个包装器。例如,如果适合您,可以使用Lazy类。也可以创建自己的包装器。

        4
  •  0
  •   John Melville    6 年前

    由于Array实现了IReadOnlyList,下面的工作就完成了。

       // Binding
       public sealed class FooModule: NinjectModule 
       {
         public opverride void Load() 
         {
            Bind<IReadOnlyList<IFoo>>().ToConstant(new IFoo[0]);
          }
       }
    
       // Injection target
       public class InjectedClass {
          public InjectedClass(IReadOnlyList<IFoo> foos) { ;}
       }