MEF构造函数注入

问题描述:

我想弄清MEF的构造函数注入属性。我不知道如何告诉它加载构造函数的参数。MEF构造函数注入

这是我试图加载

[ImportMany(typeof(BUsers))] 
public IEnumerable<BUsers> LoadBUsers { get; set; } 

这里是我使用导入组件代码中的财产。

try 
{ 
    var catalog = new AggregateCatalog(); 
    catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); 
    catalog.Catalogs.Add(new DirectoryCatalog("DI")); 
    var container = new CompositionContainer(catalog); 
    container.ComposeParts(this); 
} 

这里是我想要当您使用ImportingConstructor属性,参数来构造成为进口加载

[Serializable] 
[Export(typeof(BUsers))] 
public class EditProfile : BUsers 
{ 
    [ImportingConstructor] 
    public EditProfile(string Method, string Version) 
    {    
     Version = "2"; 
     Action = "Edit"; 
     TypeName = "EditProfile"; 
    } 

类。默认情况下,您导入的内容(合同名称)基于您要导入的参数或属性的类型。因此,在这种情况下,您的导入的合同类型是字符串,并且第一个和第二个参数之间没有实际差异。

它看起来像你正在尝试使用导入来提供配置值,这不一定是它的设计目的。为了得到它做你想要什么,你应该为每个参数的重写合同的名称,如:

[ImportingConstructor] 
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version) 
{ } 

然后,你需要方法和出口版本在你的容器。这样做的一种方式就是直接添加:

var container = new CompositionContainer(catalog); 
container.ComposeExportedValue("Method", "MethodValue"); 
container.ComposeExportedValue("Version", "2.0"); 
container.ComposeParts(this); 

(注意ComposeExportedValue实际上是对静态AttributedModelServices类中定义的扩展方法。)

如果你想从配置读取这些值可以创建自己的导出提供程序,该提供程序读取配置并提供其中的值作为导出到容器。

处理这种情况的另一种方法是只导入一个接口,该接口通过名称提供对配置值的访问,并从构造函数的主体中获取所需的值。

+0

我刚刚在CodePlex上下载了一个新的。 ComposeExportedValue()的方法不在CompositionContainer的类中。它在哪里? – 2010-01-20 22:18:51

+0

我想我找到了方法。它属于AttributedModelServices类,其中方法被定义为类CompositionContainer的扩展方法。 – 2010-01-20 22:32:20

+1

@ David.Chu.ca是的,ComposeExportedValue是AttributedModelServices类的扩展方法。 – 2010-01-21 18:33:14

我喜欢丹尼尔的解决方案;然而,我所看到的只有一件事是参与者名称(创建CompopositionContrainer())和导出部分与[ImportingConstructor]之间的自定义CTOR紧密耦合。例如,“方法”在两个地方都有两个匹配。如果参与者和导出部分处于差异项目中,则难以维护导出部分。

如果可能,我会将第二个CTOR添加到Export部件类。例如:

[Export(typeof(BUsers))] 
public class EditProfile : BUsers 
{ 
    [ImportingConstructor] 
    public EditProfile(EditProfileParameters ctorPars) 
    : this(ctorPars.Method, ctorPars.Version) {} 

    public EditProfile(string Method, string Version) 
    { 
     Version = "2"; 
     Action = "Edit"; 
     TypeName = "EditProfile"; 
    } 

类EditProfileParameters应该是直截了当:方法和版本的两个属性:

[Export] 
public class EditProfileParameters{ 
    public string Method { get; set; } 
    public string Version { get; set; } 
} 

关键的一点是要导出的属性添加到类。然后MEF应该能够将该类映射到EditProfile的CTOR的参数。

下面是例子,导出一部分添加到容器:

var container = new CompositionContainer(catalog); 
var instance1 = new EditProfileParameters(); 
// set property values from config or other resources 
container.ComposeExportedValue(instance1); 
container.ComposeParts(this); 

虽然太迟了,这里是一个利用MEF的鲜为人知的功能的另一种方法:房产出口

public class ObjectMother 
{ 
    [Export] 
    public static EditProfile DefaultEditProfile 
    { 
     get 
     { 
      var method = ConfigurationManager.AppSettings["method"]; 
      var version = ConfigurationManager.AppSettings["version"]; 

      return new EditProfile(method,version); 
     } 
    } 
} 

ObjectMother不需要使用这些工具,EditProfile也不需要任何属性。

+0

不错的功能,但如果'EditProfile'包含任何导入?在这种情况下,您需要在容器上调用“SatisfyImportsOnce”。这很痛。目前我对这个问题没有真正的解决方案。 – 2015-10-13 14:38:50

+0

在这种情况下,我们正在构建一个手动实例化EditProfile的工厂。如果EditProfile在构造函数中需要额外的依赖关系,则可以通过ImportingConstructor始终将这些依赖关系带入Factory。我应该指出,如果向EditProfile添加其他依赖项,这是应用程序中此构造函数的唯一引用,并且您将收到编译时错误。这是一个公平交易,恕我直言。 – bryanbcook 2015-10-14 18:00:29