如何使用Ninject实例化MEF导出对象? [英] How to instantiate a MEF exported object using Ninject?
问题描述
我的应用程序正在使用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 $中找到类型(Ninject:通常通过
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 Module
s 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屋!