如何使用MEFinheritance导出和MetaData?

我有一个界面:

[InheritedExport(typeof(IMetric))] public interface IMetric { ... } 

我有一个Meta属性界面:

  public interface IMetricAttribute { ... } 

以及实现它的属性:

 [MetadataAttribute] [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class MetricAttribute : ExportAttribute, IMetricAttribute { public string MetricName { get; set; } public string MetricDescription { get; set; } public MetricAttribute(string name, string description) : base(typeof(MetricAttribute)) { this.MetricName = name; this.MetricDescription = description; } } 

然后我有两个class:

 [Metric("MetricA","MetricA")] public class MetricA: IMetric { ... } [Export(typeof(IMetric))] <<<< THIS IS IMPORTANT [Metric("MetricB", "MetricB")] public class MetricB: IMetric { ... } 

然后我尝试导入指标(我可以在目录中看到)

以下返回MetricA和MetricB

 var metrics = compositionContainer.GetExports(); 

但是,以下仅返回MetricB和NOT MetricA

 var metrics = compositionContainer.GetExports(); 

知道为什么吗?

(注意MetricB上的重复导出(它已经实现了IMetric))

谢谢

大卫

我第一次看到这种行为,但据我所知,元数据是在类型级别的每次导出生成的。 所以,给出:

 [Metric("MetricA", "MetricA")] public class MetricA : IMetric { } 

您有两种此类型的导出。 您具有由MetricAttribute提供的MetricAttribute ,并且您具有由接口上的InheritedExport(typeof(IMetric))属性提供的IMetric的inheritance导出。

如果查看容器,您会注意到为MetricA定义了两个导出。 这是第一个,其元数据:

在此处输入图像描述

这是第二个:

在此处输入图像描述

您会注意到元数据是在导出MetricA ,而不是inheritance的导出。 如果我添加了另一个导出,让我们说[Export("test")]MetricA ,您将获得另一个导出定义,其中MetricNameMetricDescription元数据项与名为“test”的合同相同。 这表明,在分析类型时,将标识export属性,并且创建的导出定义包括在抽象树中的同一级别指定的元数据。

执行所需操作的最简单方法是删除InheritedExport ,并将MetricAttribute的定义修改为:

 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute] public class MetricAttribute : ExportAttribute, IMetricAttribute { public MetricAttribute(string name, string description) : base(typeof(IMetric)) { this.MetricName = name; this.MetricDescription = description; } public string MetricName { get; private set; } public string MetricDescription { get; private set; } } 

然后,您将typeof(IMetric)传递给基础ExportAttribute构造函数。 然后,您可以正确获取GetExports()GetExports()的两个导出。

我遇到了同样的问题,发现了一个不同的解决方案,对我来说很好用:我只是在界面中添加了元数据!

 [InheritedExport(typeof(IMetric))] [Metric("name","description")] public interface IMetric { ... } 

您可以将这些字段留空或默认使用null,但在此处指定元数据非常重要。 然后指定没有export属性的类:

 [Metric("MetricA")] public class MetricA: IMetric { ... } 

请注意,您可以只指定一个元数据,但在这种情况下第二个不会是description ,它将为null ! 因此,界面中的元数据不是默认值。 总而言之,这对我有用,我可以将InheritedExport与我的元数据一起使用:-)

澄清马修答案:

在定义自定义元数据属性类MetricAttribute并从ExportAttributeinheritance时,实质上是将[Export]属性添加到使用[Metric]属性装饰的所有类中。 这意味着您不再需要接口上的[InheritedExport]属性,因为它只创建单独的导出定义而没有任何元数据。

如果要创建更可重用的元数据属性,可以在MetricAttribute公开ExportAttribute构造函数参数,如下所示:

 public MetricAttribute(Type contractType, string name, string description) : base(contractType) { this.MetricName = name; this.MetricDescription = description; } 

通过引入contractType变量,您现在可以补充您的定义

 [Export(typeof(IMetric))] [Metric("MetricB", "MetricB")] public class MetricB: IMetric { ... } 

有:

 [Metric(typeof(IMetric), "MetricB", "MetricB")] public class MetricB: IMetric { ... }