使用AllowMultiple = true的自定义MEF ExportAttribute会导致重复

Ath*_*ari 4 c# extensibility mef custom-attributes

我想导出类型 Foo具有多个元数据选项的:

public interface IFoo
{
    void Do ();
}

[ExportFoo ("Bar", "1.0")]
[ExportFoo ("Baz", "1.0")]
[ExportFoo ("Baz", "2.0")]
public class Foo : IFoo
{
    public void Do () {}
}
Run Code Online (Sandbox Code Playgroud)

我已经宣布了 ExportFooAttribute这样说了:

public interface IFooMeta
{
    string Name { get; }
    string Version { get; }
}

[MetadataAttribute, AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
public class ExportFooAttribute : ExportAttribute, IFooMeta
{
    public string Name { get; private set; }
    public string Version { get; private set; }

    public ExportFooAttribute (string name, string version) : base(typeof(IFoo))
    {
        Name = name;
        Version = version;
    }
}
Run Code Online (Sandbox Code Playgroud)

根据文档,何时AllowMultiple设置为true,元数据实际上包含原始元数据的属性数组,所以我这样导入类型:

public interface IFooMultiMeta
{
    string[] Name { get; }
    string[] Version { get; }
}

public class Program
{
    [ImportMany]
    public List<Lazy<IFoo, IFooMultiMeta>> Foos { get; set; }

    private static void Main ()
    {
        new Program().MainInternal();
    }

    private void MainInternal ()
    {
        new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly())).ComposeParts(this);
        foreach (Lazy<IFoo, IFooMultiMeta> lazyFoo in Foos)
            for (int i = 0; i < lazyFoo.Metadata.Name.Length; i++)
                Console.WriteLine("* {0} {1}", lazyFoo.Metadata.Name[i], lazyFoo.Metadata.Version[i]);
        Console.WriteLine(Equals(Foos[0].Metadata, Foos[1].Metadata));
        Console.ReadKey();
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望得到一个实例 Foo包含元数据的其中包含3个值的数组.但是,我得到了这个:

* Baz 2.0
* Baz 1.0
* Bar 1.0
* Baz 2.0
* Baz 1.0
* Bar 1.0
* Baz 2.0
* Baz 1.0
* Bar 1.0
False
Run Code Online (Sandbox Code Playgroud)

更糟糕的是,元数据实例是不同的,所以我甚至无法正确筛选出重复项.

题:如何正确导出一个类以满足多个元数据属性组合?

完整示例:http://pastebin.com/WyjN95gr

Pan*_*nis 9

这三个导出的原因是您从中导出自定义导出元数据 ExportAttribute.这意味着每个装饰都会发生不同的出口.三个装饰导致三个出口.

我不确定为什么每个导出都会获得所有{Name,Version}对.

要克服这三个导出,您可以更新自定义属性以从Attribute派生:

[MetadataAttribute, AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
public class ExportMetaFooAttribute : Attribute, IFooMeta
{
    public string Name { get; private set; }
    public string Version { get; private set; }

    public ExportFooAttribute (string name, string version)
    {
        Name = name;
        Version = version;
    }
}
Run Code Online (Sandbox Code Playgroud)

我已将其重命名为,ExportMetaFooAttribute因为它不是导出属性,而是导出元数据属性.

然后你将你的Foo班级改为:

[Export(typeof(IFoo))]
[ExportMetaFoo("Bar", "1.0")]
[ExportMetaFoo("Baz", "1.0")]
[ExportMetaFoo("Baz", "2.0")]
public class Foo : IFoo
{
    public void Do ()
    {}
}
Run Code Online (Sandbox Code Playgroud)

正如您现在所看到的,我们需要额外的内容ExportAttribute来指定需要导出此类.

  • 名称/版本对经过多次,因为属性是导出属性和元数据属性.对于三个导出中的每个导出,所有三个属性的值也作为元数据拉入. (3认同)