41

我正在尝试找出 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);
}

这是我要加载的课程

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

3 回答 3

58

当您使用 ImportingConstructor 特性时,构造函数的参数变为导入。默认情况下,您要导入的内容(合同名称)基于您要导入的参数或属性的类型。因此,在这种情况下,您的两个导入的合同类型都是字符串,第一个参数和第二个参数之间没有真正的区别。

看起来您正在尝试使用导入来提供配置值,这不一定是它的设计目的。为了让它做你想做的事,你应该覆盖每个参数的合约名称,如下所示:

[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 类上定义的扩展方法。)

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

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

于 2010-01-05T18:48:14.317 回答
24

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

如果可能的话,我会将第二个 CTOR 添加到导出部件类中。例如:

[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 的类应该很简单:Method 和 Version 的两个属性:

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

关键是在类中添加Export 属性。那么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);
于 2010-01-21T18:25:09.270 回答
1

虽然迟到了,但这里有另一种利用 MEF 鲜为人知的功能的方法:Property Exports

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 上不需要任何属性。

于 2015-10-05T17:16:40.620 回答