如何使用 Ninject 实例化 MEF 导出对象?
我的应用程序使用 MEF 从外部程序集中导出一些类。这些类是为构造函数注入而设置的。我面临的问题是 当我尝试访问这些类时,MEF 正在尝试实例化这些类。有没有办法让 Ninject 负责类的实例化?
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 创建它的实例。我不太确定我是否想要懒惰。
[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 模块中,而不是它们所在的程序集中)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用 Ninject
Load
机制 将导出的类混合在一起,并且您可以:创建是惰性的(即
IMyInterface
的每个 impl是在迭代上面的 IIRC 时动态创建的,但请查看 源代码 (这是非常干净和可读的,你没有借口:P)可以肯定。如果您不需要懒惰,请使用 LINQ 的
ToArray
或ToList
来获取IMyInterface[]
或List
>或者您可以使用低级
Resolve()
系列方法(再次查看示例测试)来获取符合条件的服务 [如果您想做一些过滤或其他操作不仅仅是使用实例 - 尽管绑定元数据可能是那里的解决方案]最后,如果您可以编辑您是否需要懒惰本身或正在这样做来说明一点的解释。 (并在这里搜索
Lazy
,一般来说,Ninject 和 autofac 都适用于某些示例 - 不记得源代码中是否有任何示例 - 不要想,因为它仍在 3.5 上)编辑:在这种情况下,您需要一个具有以下功能的绑定:
在子程序集的模块中的注册中。
然后,当您在父程序集中进行解析时,您可以使用
Kernel.Get<>
重载,该重载采用name
参数来指示您想要的参数(无需惰性、数组或 IEnumerable)。Named
机制是 Ninject 中绑定元数据概念的特定应用(仅一两个辅助扩展根据广义概念实现它) - 如果超出简单名称的某些内容,则有足够的空间来自定义它是不够的。如果您使用 MEF 构建对象,则可以使用
Kernel.Inject()
机制注入属性。问题是 MEF 或 Ninject- 必须找到类型(Ninject:通常通过
Module
中的Bind()
或通过扫描扩展,之后可以执行Resolve
在实例化之前对绑定进行子集化 - 尽管这不是您通常做的事情)- 必须实例化类型(Ninject:通常通过
Kernel.Get()
,但如果您通过 MEF 等发现类型,则可以使用Kernel.Get(类型)重载
)
- 必须注入类型(Ninject:通常通过
Kernel.Inject()
或隐含在 `Kernel.Get() 中)我还不清楚为什么你觉得你需要混合并破坏两者 - 最终在构造和构造函数注入期间共享职责不是这两个库的核心用例,即使它们都是非常可组合的库。你是否有限制,或者双方都有关键的利益?
You could use the Ninject
Load
mechanism to get the exported classes into the mix, and the you either: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.If you dont need the laziness, use LINQ's
ToArray
orToList
to get aIMyInterface[]
orList<IMyInterface>
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]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)EDIT: In that case, you want a bind that has:
in the registrations in your modules in the child assembly.
Then when you're resolving in the parent assembly, you use the
Kernel.Get<>
overload that takes aname
parameter to indicate the one you want (no need for laziness, arrays orIEnumerable
). TheNamed
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.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()
inModule
s or via scanning extensions, after which one can do aResolve
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 theKernel.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?
您可以使用 ExportFactory 创建实例
请参阅此处的文档:
http://mef.codeplex.com/wikipage?title=PartCreator
你的情况会略有不同
我也会使用元数据和自定义属性
,或者使用没有元数据的
return Controllers.First()
然后你可以围绕它编写 ninject 部分,甚至坚持使用 MEF
希望这有帮助
You can use ExportFactory to create Instances
see docs here:
http://mef.codeplex.com/wikipage?title=PartCreator
Your case would be slitly different
I would use Metadata and a custom attribute also
or use
return Controllers.First()
without the MetadataThen you can code the ninject parts around that or even stick with MEF
Hope this helps