【问题标题】:Importing objects in a default constructor using MEF使用 MEF 在默认构造函数中导入对象
【发布时间】:2015-07-28 18:03:04
【问题描述】:

我真的认为这还没有被问到,并且不确定之前是否有人遇到过这个问题

所以我正在与 MEF 合作,并有一个像下面这样的课程 -

[Export]
public class MyClass : IBase
{

private IEnumberable<IMyAddin> _theAddin;

//Default constructor will NOT be
//used because the ImportingConstructor
//attribute is present.
public MyClass() 
{ 
    foreach (var addin in _theAddin)
        DoSomeVeryImportantWork(addin);
}

//This constructor will be used.
//An import with contract type IMyAddin is 
//declared automatically.
[ImportingConstructor] 
public MyClass([ImportMany]IEnumberable<IMyAddin> MyAddin;) : this()
{
    _theAddin = MyAddin;
}

}

我有一个类似下面的方法 -

T GetById<T>(Guid id) where T:IBase, new()
{
    var x = new T(); 
    //Do some processing
    return x
}

问题是,由于我正在做一个新的 T(),默认构造函数不知道任何关于 _TheAddin 的信息并且为空。

以前有人遇到过这种情况吗?如果问题不清楚,请告诉我,我可以提供更多详细信息。

我尝试从默认构造函数中删除 [ImportingConstructor],但它不起作用。如何填充 _theAddin?

提前致谢!

编辑: 我也试过如下,不行-

[Export]
public class MyClass : IBase
{

[ImportMany]
private IEnumberable<IMyAddin> _theAddin;

//Default constructor will NOT be
//used because the ImportingConstructor
//attribute is present.
public MyClass() 
{ 
    foreach (var addin in _theAddin)
        DoSomeVeryImportantWork(addin);
}


}

【问题讨论】:

  • 是的,我正在这样做。这是 web api 代码的一部分,我构建了一个容器并输入 web api IDependencyResolver。
  • 你的方法有几个缺陷。首先,如果某些东西是组件/可注入的,需要由容器自动连接,不要自己新建它。让您的容器执行此操作。其次你的component's constructor should be simple,所以你不应该在ctor中做一些非常重要的工作。第三,你的组件应该always only have 1 single constructor
  • 请在@Steven 下方查看我的评论。同意你的观点,同时拥有 new() 和尝试注入可能不是最好的方法。谢谢!

标签: c# .net dependency-injection containers mef


【解决方案1】:

您可能希望自己创建底层的 CompositionContainer 并提供一些静态方法来从中检索对象。您还可以直接公开您的容器,以便您可以从任何地方访问 SatisfyImportsOnce()、GetExport() 等方法。

注意:您可以摆脱执行导入的 ctor 并直接使用 [ImportMany] 装饰您的私有字段。这样,在创建新的 T() 后,您可以调用 yourContainer.SatisfyImportsOnce(your_T_instance)。

有关详细信息,请参阅msdn 上的示例。

【讨论】:

  • 感谢您的建议!正如另一条评论中提到的,这是 Web Api 代码的一部分,我确实有一个容器,用于实现 IDependecyResolver 并传递给 MVC 运行时以解析对象。不确定我是否遗漏了什么,但是一旦分配给 global.asax 之外的 DependecnyResolver,我就无法访问容器。
  • 而且您也无权访问 IDependencyResolver 实现?
  • 我有,请看下面 Global.asax GlobalConfiguration.Configuration.DependencyResolver = new MefApiDependencyResolver(container);
  • 好吧,那么你不能用 var x = new T() 代替 var x = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(T)) as T 吗?
  • 我们改变了整个方法本身,因为朝这个方向发展并不合逻辑。这与上面 Steven 的评论一致,如果我们想要注入一些东西,我们不应该更新。我们最终使用反射动态调用所需的过程,而不是依赖构造函数为我们连接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
  • 2017-04-01
  • 1970-01-01
相关资源
最近更新 更多