【问题标题】:Custom MEF ExportAttribute with AllowMultiple=true causes duplicationAllowMultiple=true 的自定义 MEF ExportAttribute 导致重复
【发布时间】:2013-07-03 21:19:34
【问题描述】:

我想用多个元数据选项导出类型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 () {}
}

我已经这样声明了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;
    }
}

根据文档,当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();
    }
}

我希望得到一个带有元数据的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

更糟糕的是,元数据实例不同,所以我什至无法正确过滤掉重复项。

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

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

【问题讨论】:

    标签: c# mef custom-attributes extensibility


    【解决方案1】:

    三个导出的原因是您从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;
        }
    }
    

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

    然后你将你的 Foo 类更改为:

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

    正如你现在看到的,我们需要额外的ExportAttribute 来指定需要导出这个类。

    【讨论】:

    • 名称/版本对多次出现,因为属性既是导出属性又是元数据属性。对于三个导出中的每一个,所有三个属性的值也作为元数据被拉入。
    • @Matt 太棒了!感谢马特的解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多