如何使用Ninject实例化MEF导出对象? [英] How to instantiate a MEF exported object using Ninject?

查看:153
本文介绍了如何使用Ninject实例化MEF导出对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序正在使用MEF从外部程序集导出一些类。这些类用于构造器注入。我遇到的问题是,
MEF尝试在尝试访问它们时实例化类。有没有办法让Ninject照顾课程的实例化?

My application is using MEF to export some classes from an external assembly. These classes are setup for constructor injection. The issue I am facing is that MEF is attempting to instantiate the classes when I try to access them. Is there a way to have Ninject take care of the instantiation of the class?

IEnumerable<Lazy<IMyInterface>> controllers = 
    mefContainer.GetExports<IMyInterface>();

// The following line throws an error because MEF is 
// trying to instantiate a class that requires 5 parameters
IMyInterface firstClass = controllers.First().Value;



更新:



有多个类实现 IMyInterface ,我想选择一个具有特定名称,然后让Ninject创建一个实例。我不太确定我是否想要懒惰。

Update:

There are multiple classes that implement IMyInterface and I would like to select the one that has a specific name and then have Ninject create an instance of it. I'm not really sure if I want laziness.

[Export(typeof(IMyInterface))]
public class MyClassOne : IMyInterface {

     private MyRepository one;
     private YourRepository two;

     public MyClassTwo(MyRepository repoOne, YourRepository repoTwo) {
            one = repoOne;
            two = repoTwo;
     }         
}

[Export(typeof(IMyInterface))]
public class MyClassTwo : IMyInterface {

     private MyRepository one;
     private YourRepository two;

     public MyClassTwo(MyRepository repoOne, YourRepository repoTwo) {
            one = repoOne;
            two = repoTwo;
     }


}

使用MEF,我想要获得 MyClassOne MyClassTwo ,然后让Ninject提供一个 MyRepository YourRepository (注意,这两个被绑定在主程序集中的Ninject模块中,而不是它们所在的程序集)

Using MEF, I would like to get either MyClassOne or MyClassTwo and then have Ninject provide an instance of MyRepository and YourRepository (Note, these two are bound in a Ninject module in the main assembly and not the assembly they are in)

推荐答案

您可以使用 Ninject 加载机制以将导出的类导入混合,你可以:

You could use the Ninject Load mechanism to get the exported classes into the mix, and the you either:

kernel.GetAll<IMyInterface>()

创建是懒惰的(即,每个元素 IMyInterface 是随机创建的迭代上述)IIRC,但是看看来源(这是非常干净和可读性,你没有借口:P)。

The creation is lazy (i.e., each impl of IMyInterface is created on the fly as you iterate over the above) IIRC, but have a look at the tests in the source (which is very clean and readable, you have no excuse :P) to be sure.

如果你不需要懒惰,使用LINQ的 ToArray ToList 获取一个 IMyInterface [] 列表< IMyInterface>

If you dont need the laziness, use LINQ's ToArray or ToList to get a IMyInterface[] or List<IMyInterface>

或者您可以使用低级 Resolve() / code>系列方法(再次,查看样本的测试)来获取合格的服务[如果你想做一些过滤或者除了使用一个实例以外的东西 - 虽然绑定的元数据可能是解决方案那里]

or you can use the low-level Resolve() family of methods (again, have a look in the tests for samples) to get the eligible services [if you wanted to do some filtering or something other than just using an instance - though binding metadata is probably the solution there]

最后,如果你可以编辑一个解释,你是否需要懒惰本身或正在做它来说明一点。 (并且在这里搜索 Lazy< T> ,并且一般来说,对于某些样本,Ninject和autofac都不能记住 - 如果源中有任何示例 - 认为不是它仍然在3.5)

Finally, if you can edit in an explanation of whether you need laziness per se or are doing it to illustrate a point. (and have a search for Lazy<T> here and in general wrt both Ninject and autofac for some samples - cant recall if there are any examples in the source - think not as it's still on 3.5)

编辑:在这种情况下,你想要一个绑定:

In that case, you want a bind that has:

Bind<X>().To<>().In...().Named( "x" );

在子组件中的模块注册中。

in the registrations in your modules in the child assembly.

然后当您在父程序集中解析时,您将使用名称 Kernel.Get<> / code>参数来指示你想要的(不需要懒惰,数组或 IEnumerable )。 命名为机制是一个特定的(只是一个或两个帮助扩展在广义概念方面实现)绑定元数据概念在Ninject中的应用 - 有足够的空间来定制它如果某个简单的名字超出了一个简单的名称,那么

Then when you're resolving in the parent assembly, you use the Kernel.Get<> overload that takes a name parameter to indicate the one you want (no need for laziness, arrays or IEnumerable). The Named mechanism is a specific (just one or two helper extensions implement it in terms of the generalised concept) application of the binding metadata concept in Ninject - there's plenty room to customise it if somethng beyond a simple name is insufficient.

如果你使用MEF构造对象,可以使用 Kernel.Inject()机制来注入属性。问题是MEF或Ninject
必须在 Module Bind() c $ c> s或通过扫描扩展名,之后可以执行解析以将实例化之前的绑定进行子集化 - 虽然这不是您通常所做的操作)
- 必须实例化类型(Ninject:通常通过 Kernel.Get(),但是如果您通过例如MEF发现了类型,则可以使用 Kernel.Get(Type) overloads
- 必须注入类型(Ninject:通常通过 Kernel.Inject(),或隐含在`Kernel.Get())

If you're using MEF to construct the objects, you could use the Kernel.Inject() mechanism to inject properties. The problem is that either MEF or Ninject - has to find the types (Ninject: generally via Bind() in Modules or via scanning extensions, after which one can do a Resolve to subset the bindings before instantiation - though this isnt something you normally do) - has to instantiate the types (Ninject: typically via a Kernel.Get(), but if you discovered the types via e.g. MEF, you might use the Kernel.Get(Type) overloads ) - has to inject the types (Ninject: typically via a Kernel.Inject(), or implicit in the `Kernel.Get())

我还不清楚,为什么你觉得你需要混合和混合这两个 - 最终在构建和注入注册过程中分担责任不是二进制文件的核心用例,两个都是可比较的图书馆。你有约束力,还是双方都有重要的好处?

What's not clear to me yet is why you feel you need to mix and mangle the two - ultimately sharing duties during construction and constructor injection is not a core use case for either lib, even if they're both quite composable libraries. Do you have a constraint, or do you have critical benefits on both sides?

这篇关于如何使用Ninject实例化MEF导出对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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