注射接口的数组中Ninject [英] Inject Array of Interfaces in Ninject

查看:137
本文介绍了注射接口的数组中Ninject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下code。

 公共接口的IFoo {}
公共类酒吧
{
    公共酒吧(的IFoo [] FOOS){}
}
公共类MyModule的:NinjectModule
{
    公共覆盖无效负载()
    {
        绑定&所述;的IFoo []≥()ToConstant(新的IFoo [0])。
        // ToConstant()仅仅是一个例子
    }
}
公共类节目
{
    私有静态无效的主要(字串[] args)
    {
        变种内核=新StandardKernel(新MyModule的());
        VAR栏= kernel.Get<酒吧及GT;();
    }
}

当我尝试运行该程序,我得到了以下异常。


  

错误激活IFoo的结果
  没有匹配的绑定是可用的,并且类型不是自我绑定。结果
  激活路径:结果
  2)依赖的IFoo注射入式酒吧
的构造函数参数FOOS
  1)请给酒吧


我怎么能注入/绑定到Ninject数组?

感谢您的时间。

编辑:结果
我的申请进口是由第三方组件创建的数据。
导入过程适用于不同类型的过滤器(例如不同的过滤器接口的实现)。过滤变化经常的规则,但太复杂,无法用纯配置(以及一个主过滤器)来完成。

我要让添加/编辑器尽可能容易。我有什么是所有的过滤器实现位于我想每一个过滤器界面下面的方法(它提供了过滤器类型的每一个执行的一个实例)绑定的程序集。基本上我想避免需要改变我的Ninject模块,当我添加/删除过滤器类。

 私人的IEnumerable< TInterface> GetInterfaceImplementations< TInterface>(IContext上下文)
    {
        返回的GetType()。Assembly.GetTypes()
            。凡(T => typeof运算(TInterface).IsAssignableFrom(T)及和放大器; IsConcreteClass(T))
            。选择(T => Kernel.Get(T))。演员LT; TInterface>();
    }

我感觉在绕过集装箱DI机制方面有点内疚。这是一个不好的做法?是否有一个普遍的做法是做这样的事情?

分辨率:结果
我使用的是包装类为bsnote建议。


解决方案

这在很大程度上是一种@ bsnote的回答(这我+ 1D),这可能在理解为什么它以这种方式帮助重述。

Ninject(和其他DI /插件框架)有两个不同的设备:


  1. 的概念,无论是绑定到一个明确的实施服务(获取

  2. 系统工具,允许一个拿到一组服务[那台编程首选之一或以某种方式跨越聚集]的( GETALL / ResolveAll 在Ninject)

您例如code恰好使用的上述2相关的语法。 (例如,在MEF,人们通常使用 [ImportMany] 注释来说明这一点)

我需要的样本看(看源 - 它真的很短,干净且易于遵循)找到一种解决方法

不过,由于@bsnote说,重构你的需求的一种方式是包装数组无论是在容器中,或者让你自讨苦吃(即工厂方法或库类型结构)

这也可能是有用的为你讲解你的真实的情况是什么 - 为什么有一个裸体的阵列?当然,有项目的集合构建乞讨被封装底层的这一切? - 这个问题肯定是犯规拿出多少

编辑:有在我想象会攻击很多你正在试图做的(在之类的东西StructureMap的东西,扩展了一组扫描的例子,这样的东西是集成度更高,这显然有优点和缺点)。

根据您是否正在努力实现约定优于配置或没有,你可能要考虑各类型的插件坚持一个标记接口。然后你可以明确地绑定各一个。另外,为COC,可以使模块加载()常规遍历在生成一套实现(即,大量个人获取取值)在您的编辑。

无论哪种方式,当你有多个注册的地方,你可以高兴地是'要求'一 T [] 的IEnumerable< T> 并获得全套。如果您要明确实现这一目标(即服务定位器和所有它意味着 - 就像你做,你可以使用 GETALL 批量他们,所以你没有做这是在路上所隐含的循环,你已经做到了。

不知道,如果你做了这个连接,或者如果我失去了一些东西。无论哪种方式,我希望这是教你沾些code成问题,因为它讲> 1000字:P

Consider the following code.

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>();
    }
}

When I try to run the program I get the following exception.

Error activating IFoo
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IFoo into parameter foos of constructor of type Bar
1) Request for Bar

How can I inject / bind to an array in Ninject?

Thanks for your time.

Edit:
My application imports data which is created by a third party component. The import process applies different kind of filters (e.g. implementations of different filter interfaces). The rules for filtering change quite often but are too complex to be done with pure configuration (and a master filter).

I want to make adding/editing filters as easy as possible. What I have is an assembly where all the filter implementations are located in. I tried to bind every filter interface to the following method (which provides an instance of every implementation of that filter type). Basically I want to avoid the need to change my Ninject module when I add/remove filter classes.

    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>();
    }

I am feeling a bit guilty in terms of bypassing the containers DI mechanism. Is this a bad practice? Is there a common practice to do such things?

Resolution:
I use a wrapper class as bsnote suggested.

解决方案

This is largely a restatement of @bsnote's answer (which I've +1d) which may help in understanding why it works in this manner.

Ninject (and other DI / addin frameworks) have two distinct facilities:

  1. the notion of either binding to a single unambiguous implementation of a service (Get)
  2. A facility that allows one to get a set of services [that one then programmatically picks one of or aggregates across in some way] (GetAll / ResolveAll in Ninject)

Your example code happens to use syntax that's associated with 2. above. (e.g., in MEF, one typically use [ImportMany] annotations to make this clear)

I'd need to look in the samples (look at the source - its really short, clean and easy to follow) to find a workaround for this.

However, as @bsnote says, one way of refactoring your requirement is to wrap the array either in a container, or to have an object that you ask for it (i.e., a factory method or repository type construct)

It may also be useful for you to explain what your real case is - why is there a naked array ? Surely there is a collection of items construct begging to be encapsulated underlying all this - this question certainly doesnt come up much?

EDIT: There are a set of scanning examples in the extensions that I imagine would attack a lot of the stuff you're trying to do (In things like StructureMap, this sort of stuff is more integrated, which obviously has pros and cons).

Depending on whether you're trying to achieve convention over configuration or not, you might want to consider sticking a marker interface on each type of plugin. Then you can explicitly Bind each one. Alternately, for CoC, you can make the Module's Load() routine loop over the set of implementations you generate (i.e., lots of individual Gets) in your edit.

Either way, when you have the multiple registrations in place you can happily either 'request' a T[] or IEnumerable<T> and get the full set. If you want to achieve this explicitly (i.e., Service Locator and all it implies - like in you're doing, you can use GetAll to batch them so you're not doing the looping that's implicit in the way you've done it.

Not sure if you've made this connection or if I'm missing something. Either way, I hope it's taught you to stick some code into questions as it speaks > 1000 words :P

这篇关于注射接口的数组中Ninject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆