MEF构造函数注入

alp*_*pha 39 c# dependency-injection mef constructor-injection

我试图找出MEF的构造函数注入属性.我不知道如何告诉它加载构造函数的参数.

这是我正在尝试加载的属性

[ImportMany(typeof(BUsers))]
public IEnumerable<BUsers> LoadBUsers { get; set; }
Run Code Online (Sandbox Code Playgroud)

这是我用来导入程序集的代码.

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);
}
Run Code Online (Sandbox Code Playgroud)

这是我正在尝试加载的类

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

Dan*_*ted 55

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

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

[ImportingConstructor]
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version)
{ }
Run Code Online (Sandbox Code Playgroud)

然后,您需要在容器中导出方法和版本.一种方法是直接添加它们:

var container = new CompositionContainer(catalog);
container.ComposeExportedValue("Method", "MethodValue");
container.ComposeExportedValue("Version", "2.0");
container.ComposeParts(this);
Run Code Online (Sandbox Code Playgroud)

(请注意,ComposeExportedValue实际上是在静态AttributedModelServices类上定义的扩展方法.)

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

处理此问题的另一种方法是只导入一个按名称访问配置值的接口,并从构造函数体中获取所需的值.


Dav*_*.ca 24

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

如果可能的话,我会将第二个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";
    }
Run Code Online (Sandbox Code Playgroud)

EditProfileParameters类应该是直截了当的:Method和Version的两个属性:

[Export]
public class EditProfileParameters{
   public string Method { get; set; }
   public string Version { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

关键是将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);
Run Code Online (Sandbox Code Playgroud)