4

这是我的第一个 SO 问题,所以请多多包涵……

我正在尝试使用 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();

然后,我将使用已配置为检查程序集列表的“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 的帖子。但他们中的大多数人都在使用非共享导出,这不是我的目标。

4

1 回答 1

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

于 2014-08-20T09:34:29.887 回答