C# 如何使用MEF继承导出&;元数据?
我有一个界面:C# 如何使用MEF继承导出&;元数据?,c#,.net,c#-4.0,mef,C#,.net,C# 4.0,Mef,我有一个界面: [InheritedExport(typeof(IMetric))] public interface IMetric { ... } 我有一个元属性接口: public interface IMetricAttribute { ... } 以及实现它的属性: [MetadataAttribute] [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class MetricAttri
[InheritedExport(typeof(IMetric))]
public interface IMetric { ... }
我有一个元属性接口:
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;
}
}
然后我有两门课:
[Metric("MetricA","MetricA")]
public class MetricA: IMetric { ... }
[Export(typeof(IMetric))] <<<< THIS IS IMPORTANT
[Metric("MetricB", "MetricB")]
public class MetricB: IMetric { ... }
[公制(“公制”、“公制”)]
公共类MetricA:IMetric{…}
[Export(typeof(imeric))]我第一次看到这种行为,但据我所知,每次导出都会在类型级别生成元数据。因此,鉴于:
[Metric("MetricA", "MetricA")]
public class MetricA : IMetric
{
}
此类型有两个导出。您有MetricA
的导出,该导出由您的MetricAttribute
隐式提供,您有接口上的InheritedExport(typeof(IMetric))
属性提供的IMetric
的继承导出
如果查看容器,您会注意到为MetricA
定义的两个导出。以下是第一个,及其元数据:
这是第二点:
您会注意到元数据是在导出MetricA
时完成的,而不是继承的导出。如果我添加了一个进一步的导出,比如说[export(“test”)]
到MetricA
,那么您将得到另一个导出定义,对于名为“test”的合同,MetricName
和MetricDescription
具有相同的元数据项。这表明,在分析类型时,将标识导出属性,并且创建的导出定义包括在抽象树的同一级别指定的元数据
最简单的方法是退出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(imeric)
传递给基本ExportAttribute
构造函数。然后,您正确地获得了GetExports()
和GetExports()
的两个导出。我遇到了相同的问题,找到了一个不同的解决方案,对我来说效果很好:
我刚刚向界面添加了元数据
[InheritedExport(typeof(IMetric))]
[Metric("name","description")]
public interface IMetric { ... }
您可以将字段留空或使用null作为默认值,但在此处指定元数据很重要。
然后指定不带导出属性的类:
[Metric("MetricA")]
public class MetricA: IMetric { ... }
请注意,您可以只指定一个元数据,但第二个元数据不会是description
。在这种情况下,它将是null
!因此,接口中的元数据不是默认值。
所有这些对我来说都很有用,我可以使用InheritedExport和我的元数据:-)来澄清我的答案:
当您定义自定义元数据属性类MetricAttribute
并从ExportAttribute
继承时,实际上是将[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 { ... }
与:
+1个有趣的问题,期待看到答案。是否可以通过以下方法解决此问题:在IMetric
上不使用InheritedExport
,而只能使用MetricAttribute
,因为您必须在派生类型上声明它。在MetricAttribute
ctor中,您可以调用base(typeof(IMetric))
。您还没有提供有关MetricAttribute
实现的更多信息,可能您已经在那里做了。@ba_friend-谢谢,我尝试了您的建议,效果很好,但我不太清楚为什么?我仍然有兴趣找出为什么原始代码对我也不起作用,我想自己尝试一下,但目前不可能。来自感谢您的详细回答。我想我明白你的意思了——总结一下:问题是元数据链接到导出,但是继承的导出似乎没有链接到已实现类上的元数据(一个奇怪的设计决策!)。一种解决方案是,如Bau friend所说,获取属性以进行导出,从而将导出和元数据链接起来。我会接受你的回答,尽管我确实想知道是否有可能将继承的导出与元数据一起使用——但也许这是我应该发布的另一个问题!再次感谢:)
public MetricAttribute(Type contractType, string name, string description)
: base(contractType)
{
this.MetricName = name;
this.MetricDescription = description;
}
[Export(typeof(IMetric))]
[Metric("MetricB", "MetricB")]
public class MetricB: IMetric { ... }
[Metric(typeof(IMetric), "MetricB", "MetricB")]
public class MetricB: IMetric { ... }