如何在MEF中从外部类库获取多个元数据属性值
MEF多属性元数据读取实现方案
前置修正点
首先先处理现有代码的两处问题,避免元数据匹配失败:
- 元数据视图接口
ISendOperationData的属性名必须和ExportMetadata的键名完全一致,你示例中使用的Organisation(英式拼写)和接口定义的Organization(美式拼写)不一致,需要统一命名。 - 你在全局和
MefPlugin类中重复定义了ISendOperation接口,需要删除重复定义,保证所有导出和导入使用同一个接口。
多属性元数据读取实现
你现有的导入逻辑IEnumerable<Lazy<ISendOperation, ISendOperationData>> operations已经支持读取多个元数据属性,operations中每个实例的Metadata属性已经包含了所有和ISendOperationData属性匹配的元数据值,只需要在查询时增加多条件匹配即可:
public ResponseModel GetDLL(ref RequestModel obj) { // 同时匹配两个元数据属性:组织标识匹配 + 方法名在配置范围内 var relevantDll = operations.FirstOrDefault(q => // 匹配组织元数据,可根据需求调整匹配规则 (q.Metadata.Organization == "*" || q.Metadata.Organization == obj.Organization) // 匹配方法元数据,拆分逗号分隔的配置值 && q.Metadata.Method.Split(',').Select(m => m.Trim()).Contains(obj.Method)); if(relevantDll == null) { return new ResponseModel { Success = false, Msg = "未找到匹配的处理插件" }; } // 调用匹配到的插件逻辑 return relevantDll.Value.SomeMethod(obj).Result; }
优化方案:自定义强类型元数据特性
为了避免手动写多个ExportMetadata容易写错键名的问题,可以自定义导出特性,编译时就能校验元数据配置:
// 自定义导出特性,继承ExportAttribute同时实现元数据接口 [MetadataAttribute] [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class SendOperationExportAttribute : ExportAttribute, ISendOperationData { // 直接实现元数据接口的属性,作为特性的配置参数 public string Organization { get; set; } public string Method { get; set; } public SendOperationExportAttribute() : base(typeof(ISendOperation)) { } }
使用时直接标记自定义特性即可,无需重复写ExportMetadata:
[SendOperationExport(Organization = "*", Method = "one,two,fife")] public class CustomSendOperation : ISendOperation { public Task<ResponseModel> SomeMethod(RequestModel obj) { // 业务逻辑实现 return Task.FromResult(new ResponseModel { Success = true }); } }
可选优化:集合类型元数据
如果你不想手动拆分逗号分隔的方法名,可以直接把元数据属性定义为集合类型,MEF原生支持集合类型元数据的读取:
// 修改元数据接口 public interface ISendOperationData { string Organization { get; } IEnumerable<string> Method { get; } } // 导出时直接传入数组 [SendOperationExport(Organization = "*", Method = new string[]{"one","two","fife"})]
查询时直接使用集合方法判断即可:
var relevantDll = operations.FirstOrDefault(q => (q.Metadata.Organization == "*" || q.Metadata.Organization == obj.Organization) && q.Metadata.Method.Contains(obj.Method));
内容的提问来源于stack exchange,提问作者cickness
相关产品推荐
相关产品推荐

