Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用MEF继承导出&;元数据?_C#_.net_C# 4.0_Mef - Fatal编程技术网

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 { ... }