像MEF中的Constructor中的InheritedExport这样的属性

时间:2012-12-13 06:53:44

标签: .net dependencies mef composition

我正在开发一个开放式应用程序,我是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。

1 个答案:

答案 0 :(得分:2)

您可以使用MEF2执行此操作。 MEF2引入了Convention-Based Programming Model,它可以取代或补充“归因编程模型”。

对于界面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 article seriesGetting started with convention-based part registration in MEF 2