MEF2如何使用基于约定的导入从CompositionHost导出中获取元数据

本文关键字:CompositionHost 导入 元数据 获取 何使用 于约定 约定 MEF2 | 更新日期: 2023-09-27 18:14:30

这是我的第一个SO问题,所以请原谅我…

我正在尝试使用ConventionBuilder类加载MEF2组件。一切都如预期的那样工作,直到我需要访问作为导入类型的属性可用的元数据。让我们假设我有以下类:

[RuntimeCheckAttribute("MyString1", "MyString2", MyEnum.Value1)]
class ImportedClass : IRuntimeCheck
{...}

现在我可以有一个convention builder实例为'IRunTimeCheck'的实例定义一个约定:

ConventionBuilder conventions = new ConventionBuilder();
conventions.ForTypesDerivedFrom<IRuntimeCheck>()
           .Export(exp => exp.AsContractType<IRuntimeCheck>()).Shared();

然后我会使用一个'CompositionHost'实例,该实例已配置为检查程序集列表。对

的调用
var runtimeChecks = container.GetExports<IRuntimeCheck>();

将创建所有导出的'IRuntimeCheck'类型的实例。

我现在的问题是如何在导出过程中访问iruntimecheck类型上的元数据。使用MEF1,我可以利用ImportMany/Lazy机制。到目前为止,我还没有找到一个很好的方法来重建MEF2的这种行为,因为'CompositionHost'上的所有导出重载都不允许我访问元数据属性。

我已经设法通过使用AddPartMetaData:

在ConventionBuilder级别添加元数据。
conventions.ForTypesDerivedFrom<IRuntimeCheck>()
           .AddPartMetadata("securityRuntimeMetadata", AddRuntimeCheckMetadata)
           .Export(exp => exp.AsContractType<IRuntimeCheck>()).Shared();
private object AddRuntimeCheckMetadata(Type arg)
{
    RuntimeCheckAttribute metadata = (arg.GetCustomAttributes<RuntimeCheckAttribute>(false) as  
                                            RuntimeCheckAttribute[]).FirstOrDefault();
    if (metadata == null)
    {
        throw new InvalidOperationException("errorMessage");
    }
    return metadata;
}

当我调试MEF2代码时,我可以看到元数据信息是在约定构建器级别添加的。但是我不知道如何再次导出这个信息。我发现了几个试图利用ExportFactory的帖子。但他们中的大多数人都从事非共享出口,这不是我的目标。

MEF2如何使用基于约定的导入从CompositionHost导出中获取元数据

正如我写的评论,我有一个类似的问题。经过一些尝试和代码步进,我得到了必要的元数据,而没有实例化类型。

这是我的ConventionBuilder配置:

var cb = new ConventionBuilder();
cb.ForTypesDerivedFrom<IHttpController>()
            .AddPartMetadata(MetadataApiControllerName, t => t.FullName)
            .Export(ex => ex.AddMetadata(MetadataApiControllerName, t => t.FullName))
            .ExportInterfaces();
cb.ForTypesMatching(t => t.BaseType != null && (
                    (t.BaseType.Name.Equals(MetadataControllerName) && !t.BaseType.Name.StartsWith("T4MVC"))
                    || t.BaseType.Name.Equals(MetadataExtentionControllerName)
                    ))
                .AddPartMetadata(MetadataControllerName, t => t.FullName)
                .Export(ex => ex.AddMetadata(MetadataControllerName, t => t.FullName))
                .ExportInterfaces();

我正在工作的MVC/Web Api项目,只需要一些控制器的一些元信息。为了得到它们,我使用Export:

var controllerExport = _compositionContainer.Container.Value.GetExports<ExportFactory<IController, IDictionary<String, Object>>>()
                    .FirstOrDefault(
                        part => part.Metadata != null &&
                                part.Metadata.ContainsKey(DefaultContainerConfiguration.MetadataControllerName) &&
                                part.Metadata.Any(v => v.Value.ToString()
                                                .EndsWith(controllerName + ControllerNameByConvention, true,
                                                CultureInfo.InvariantCulture)));

ExportFactory对象提供了所请求的元数据字典(IDictionary<String, Object>)。