【问题标题】:How to use MEF Inherited Export & MetaData?如何使用 MEF 继承的导出和元数据?
【发布时间】:2011-07-04 11:37:16
【问题描述】:

我有一个界面:

[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;
    }
}

然后我有两个类:

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

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

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

以下返回是 MetricA AND MetricB

var metrics = compositionContainer.GetExports<IMetric>();

但是,以下仅返回 MetricB 而不是 MetricA

var metrics = compositionContainer.GetExports<IMetric, IMetricAttribute>();

知道为什么吗?

(注意 MetricB 上的重复导出(它已经从实施 IMetric 中得到))

谢谢

大卫

【问题讨论】:

  • +1 有趣的问题,期待看到答案。是否可以通过以下方法解决此问题:而不是在IMetric 上使用InheritedExport,您只能使用MetricAttribute,因为无论如何您都必须在派生类型上声明它。在MetricAttribute ctor,您可以致电base(typeof(IMetric))。您还没有提供有关 MetricAttribute 实现的更多信息,也许您已经在那里这样做了。
  • @ba_friend - 谢谢我已经尝试了你的建议,虽然我不太清楚为什么?我仍然有兴趣找出为什么原始代码不起作用
  • 我也是,我想自己尝试,但目前不可能。

标签: c# .net c#-4.0 mef


【解决方案1】:

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

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

}

此类型有两个导出。你有 MetricA 的导出,这是由你的MetricAttribute 隐式提供的,你有IMetric 的继承导出,由你界面上的InheritedExport(typeof(IMetric)) 属性提供。

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

这是第二个:

您会注意到元数据是在导出MetricA 时完成的,而不是继承的导出。如果我添加了进一步的导出,比如说[Export("test")]MetricA,你会得到另一个导出定义,对于名为“test”的合约,MetricNameMetricDescription 具有相同的元数据项。这向您表明,在分析类型时,会识别导出属性,并且创建的导出定义包括在抽象树中同一级别指定的元数据。

做你想做的最简单的方法是删除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&lt;IMetric&gt;()GetExports&lt;IMetric, IMetricAttribute&gt;() 的两个导出。

【讨论】:

  • 感谢您的详细回答。我想我明白你的意思 - 总结一下:问题是元数据与导出相关联,但是继承的导出似乎没有链接到已实现类的元数据(一个奇怪的设计决定!)。然后,一种解决方案是 ba_friend 所说的获取属性以进行导出,以便将导出和元数据链接起来。我会接受您的回答,尽管我确实想知道是否可以将继承的导出与元数据一起使用 - 但也许这是我应该发布的另一个问题!再次感谢:)
【解决方案2】:

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

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

您可以将字段留空或使用 null 作为默认值,但在此处指定元数据很重要。 然后你指定你的类没有导出属性:

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

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

【讨论】:

    【解决方案3】:

    为了澄清马修的答案:

    当您定义自定义元数据属性类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 { ... }
    

    与:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-05
      相关资源
      最近更新 更多