MEF在基类中的ImportMany导入所有组件的所有导出 - 如何防止这种情况?

时间:2012-08-26 09:17:09

标签: .net dependencies mef composition

我正在使用MEF从几个程序集中组合导出的类型。我正在使用一个基类,它应该是派生类中指定的ImportMany依赖项。它看起来像这样:

基础组装:

public abstract class BaseClass
{
    [ImportMany(typeof(IDependency)]
    public IEnumerable<IDependency> Dependencies { get; private set; }

    protected BaseClass()
    {
        var catalog = GetCatalog();
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }

    protected abstract ComposablePartCatalog GetCatalog();
}

汇编A:

[Export(typeof(BaseClass))]
public class MyA : BaseClass
{
    protected override ComposablePartCatalog GetCatalog()
    {
        return new AssemblyCatalog(Assembly.GetExecutingAssembly());
    }
}

[Export(typeof(IDependency)]
public class DependencyA1 : IDependency {}

[Export(typeof(IDependency)]
public class DependencyA2 : IDependency {}

大会B:

[Export(typeof(BaseClass))]
public class MyB : BaseClass
{
    protected override ComposablePartCatalog GetCatalog()
    {
        return new AssemblyCatalog(Assembly.GetExecutingAssembly());
    }
}

[Export(typeof(IDependency)]
public class DependencyB1 : IDependency {}

[Export(typeof(IDependency)]
public class DependencyB2 : IDependency {}

然后我在基础组件中编写所有内容:

static void Main(string[] args)
{
    DirectoryCatalog catalog = new DirectoryCatalog(path, "*.dll");
    var container = new CompositionContainer(catalog);
    IEnumerable<BaseClass> values = container.GetExportedValues<BaseClass>();

    // both BaseClass instances now have 4 Dependencies - from both Assemby A and Assembly B!
}

我遇到的问题是,当我使用MEF同时撰写MyAMyB时,每个都包含来自两个程序集的导出的IDependency - !我只希望MyA包含导出DependencyA1DependencyA2,与MyB相同。

我知道我可能应该使用依赖注入容器,但是我希望可以使用MEF吗?

2 个答案:

答案 0 :(得分:1)

在另一个作品的鼻子下做一个作品非常讨厌;)。

所以我决定手动调用container.GetExportedValues并在构造函数中自己设置属性,这样你就可以一起摆脱[ImportMany]了。 它不会被外部构图所操纵。

HTH 爱丽儿

答案 1 :(得分:1)

你正在围绕MEF做一些奇怪的舞蹈,这种方法你基本上是多次编写BaseClass,它将根据最后发生的合成给你不同的结果。代码当前编写的方式是在Main中发生的组合将是最后设置ImportMany的组合,因为这是在构造函数调用BaseClass之后发生的。与Ariel类似,我建议你不要在同一个对象上做多个作文。

如果您必须使用MEF做这样的事情,我可以通过以下几种方式看到它可能有效: 1)不要在构造函数中执行第二个组合,而是使用IPartImportsSatisfiedNotification并在OnImportsSatisifed中执行第二个组合,尽管在第二次组合时要注意第二次调用此方法。 2)执行Ariel建议并且不使用ImportMany,而只是使用GetExportedValues将该字段设置为其他程序集级别目录。请记住,这仍然是一个很大的假设,即每个程序集只会有一个派生类,否则你仍会遇到重叠。 3)您可以将ImportMany移动到派生类中,并为每个派生类型(即IADependency或IBDendency)导入唯一的依赖关系类型。 4)您可以使用元数据来过滤特定派生类型的导入。

我不确定这些是否完美,但如果我选择一个选项,我可能会选择#4的一些变体,并使用元数据来过滤导入。请参阅How does MEF determine the order of its imports?,其中显示了如何订购导入,但存在类似的代码示例以过滤它们。