1

我正在开发一个开放式应用程序,我是 MEF 的新手。我需要从派生类中完全隐藏 MEF。所以这是我的场景。

我有一个 BaseAssembly

public class ListContainer
{
    [ImportMany(typeof(IBase))]
    public List<IBase> MyObjects { get; set; }

    public void AssembleDriverComponents()
{
     .... Some code to create catalogue..
     //Crete the composition container
        var container = new CompositionContainer(aggregateCatalog);

        // Composable parts are created here i.e. the Import and Export components assembles here
        container.ComposeParts(this);
}
}

 [InheritedExport(typeof(IBase))]
public abstract class Base : IBase
{
    private IInfoBase infoBase;

    //This is something which I want to do. If I have a derived class from Base. 
      Then It does not need to use ImportingConstructor.
    [ImportingConstructor()]
    public Base(InfoBase nfoBase)
    {
        this.infoBase = infoBase;
    }
}

[InheritedExport(typeof(IInfoBase))]
public interface IInfoBase
{
    string Category { get; set; }
}


public class InfoBase : IInfoBase
{

    public string Category
    {
        get;
        set;
    }
}

其他组件将参考基础组件。

ReferenceAssembly 将有

public class Derived : Base
{
    public Derived(BaseInfo info)
        : base(info)
    {
        info.Category = "CategoryA";
    }
}

在这种情况下,MEF 不会为派生对象创建对象。

总之,我还需要像 InheritedExport 这样的 ImportingConstructor 。

4

1 回答 1

2

您可以使用 MEF2 执行此操作。MEF2 引入了基于约定的编程模型,它可以替代或补充“属性化编程模型”。

对于接口IBase

public interface IBase { }

抽象基类Base

[InheritedExport(typeof(IBase))]
public abstract class Base : IBase
{
    private IInfoBase infoBase;

    //No ImportingConstructorAttribute. This will be set with conventions.
    public Base(IInfoBase infoBase)
    {
        this.infoBase = infoBase;
    }
}

几个Base实现:

public class Derived : Base
{        
    public Derived(IInfoBase info)
        : base(info)
    {
        info.Category = "CategoryA";
    }
}

public class AnotherDerived : Base
{
    public AnotherDerived(IInfoBase info)
        : base(info)
    {
        info.Category = "CategoryB";
    }
}

info接口不变:

[InheritedExport(typeof(IInfoBase))]    
public interface IInfoBase
{
    string Category { get; set; }
}

添加了 PartCreationPolicyAttribute,以便导出的部件不会在 Base 的实现之间共享。不过这没关系。

[PartCreationPolicy(CreationPolicy.NonShared)]
public class InfoBase : IInfoBase
{
    public string Category
    {
        get;
        set;
    }
}

最后是ListContainer

public class ListContainer
{
    [ImportMany(typeof(IBase))]
    public List<IBase> MyObjects { get; set; }

    public void AssembleDriverComponents()
    {
        var regBuilder = new RegistrationBuilder();
        //SelectConstructor is the equivalent of the ImportingConstructorAttribute.
        //Note that my approach here is very crude. Simply use the first constructor.
        regBuilder.ForTypesDerivedFrom<Base>().SelectConstructor(ctors => ctors.First());

        //Only an AssemblyCatalog for this example. Note that the registration 
        //builder is used here.
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly(), regBuilder);
        //Crete the composition container
        var container = new CompositionContainer(catalog);

        // Composable parts are created here i.e. the Import and Export components assembles here
        container.SatisfyImportsOnce(this);
        System.Diagnostics.Debug.Assert(this.MyObjects.Count == 2);
    }
}

有关 MEF 约定的更多信息: MEF 2 文章系列和MEF 2中基于约定的部件注册入门

于 2013-02-05T00:50:46.723 回答