我正在尝试将基于.NET Framework的应用程序集合移植到.NET Core,作为此过程的一部分,我需要从使用MEF1切换到MEF2。我在围绕与MEF2有关的问题时遇到了很多困难(尽管我发现this post真的很有帮助),但我最近偶然发现其中一个我曾经有过的原因
特别是,我有许多使用自定义ExportAttribute
导出元数据的类,我想将它们全部导入到另一个类中,并根据此元数据对其进行过滤。这在MEF1中都运行良好,但在MEF2中,我遇到了诸如“ x 的导出元数据缺失且没有提供默认值”等问题。“
更具体地说,我注释了我的导出类,如下所示:
[Export(typeof(IClientRequestProcessor<RelaySystemModel>))]
[TargetDevice("<<Foo>>")]
internal class RelaySystemClientRequestProcessor : IClientRequestProcessor<RelaySystemModel>
{
}
然后在其他地方,我会尝试像这样导入它们:
[ImportMany]
public IEnumerable<ExportFactory<IClientRequestProcessor<RelaySystemModel>, DeviceSpecific>> RelayRequestProcessors { private get; set; }
然后,在满足导入时,尝试按元数据过滤它们:
private static IEnumerable<ExportFactory<T, DeviceSpecific>> FilterForFoo<T>(IEnumerable<ExportFactory<T, DeviceSpecific>> items)
{
return from it in items where it.Metadata.DeviceId == "<<Foo>>" select it;
}
TargetDeviceAttribute
的定义如下:
[MetadataAttribute, AttributeUsage(AttributeTargets.Class)]
public class TargetDeviceAttribute : ExportAttribute, IDeviceSpecific
{
public TargetDeviceAttribute(string deviceId)
{
this.DeviceId = deviceId;
}
public string DeviceId { get; private set; }
}
我发现正在发生的事情是部分 RelaySystemClientRequestProcessor
对应两个 exports :IClientRequestProcessor<RelaySystemModel>
,这是导出我'我感兴趣的界面和我试图用RelaySystemClientRequestProcessor
导入零件的界面。但是,“DeviceId”元数据仅与后者相关联而不是前者,这没有帮助。
我认为有几种方法可以解决,但我还没有完全测试过:
将属性ExportMetadata("DeviceId", "<<foo>>")
应用于我的所有导出部分。
更改TargetDeviceAttribute
以使用构造函数public TargetDeviceAttribute(string deviceId, Type exportType) : base(exportType)
。
我不赞成这些解决方案;如果我想更改元数据键,前者会出现问题,两者都会涉及改变我导出所有部件的方式。
我想知道的是,MEF2是否提供了一种方法来导出MEF1中的元数据:通过创建自定义元数据属性并将其应用于与部件关联的所有导出。这可能吗?
答案 0 :(得分:1)
原来我只需要删除6个字符。它不应该从TargetDeviceAttribute
继承ExportAttribute
,而应该只从Attribute
继承而来:
[MetadataAttribute, AttributeUsage(AttributeTargets.Class)]
public class TargetDeviceAttribute : Attribute, IDeviceSpecific
{
public TargetDeviceAttribute(string deviceId)
{
this.DeviceId = deviceId;
}
public string DeviceId { get; private set; }
}
在更一般的情况下,这意味着任何可以与多种可能类型相关联的元数据,但应该确保比ExportAttribute("foo", "bar")
更好的静态类型安全性/可维护性,我应该如下所示:
public interface IMetadataExtension
{
string Foo { get; }
}
public class MetadataExtension : IMetadataExtension
{
public string Foo { get; set; }
}
[MetadataAttribute]
public class MetadataExtensionAttribute : Attribute, IMetadataExtension
{
public MetadataExtensionAttribute(string foo)
{
Foo = foo;
}
public string Foo { get; }
}
[Export]
[MetadataExtension("bar")]
public class SomeExport
{
}