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

时间:2014-07-24 13:34:58

标签: c# metadata mef2

这是我的第一个问题,所以请耐心等待......

我正在尝试使用ConventionBuilder类加载MEF2的组件。在我需要访问可在导入类型上作为属性使用的元数据之前,所有内容都可以正常工作。我们假设我有以下课程:

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

现在我可以使用一个ConventionBuilder实例来定义' IRunTimeCheck'的实例约定:

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

然后我会使用一个&#39; CompositionHost&#39;已配置为检查程序集列表的实例。致电

var runtimeChecks = container.GetExports<IRuntimeCheck>();
然后

将创建所有导出的&#39; IRuntimeCheck&#39;的实例。类型。

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

我已设法使用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的帖子。但他们中的大多数都在与非共享出口合作,这不是我的目标。

1 个答案:

答案 0 :(得分:2)

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

这是我的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项目,只需要一些控制器的元信息。 要获得它们,我使用此导出:

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>)。