如何使用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
,您将获得另一个导出定义,其中MetricName
和MetricDescription
元数据项与名为“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
并从ExportAttribute
inheritance时,实质上是将[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 { ... }