MEF2, как получить метаданные из экспорта CompositionHost с импортом на основе соглашения

Это мой первый ТАК вопрос, поэтому, пожалуйста, потерпите меня...

Я пытаюсь загрузить компоненты с MEF2, используя класс ConventionBuilder. Все работает как положено, пока мне не понадобится доступ к метаданным, которые доступны как атрибуты для импортируемого типа. Предположим, у меня есть следующий класс:

[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 не позволяют мне получить доступ к атрибутам метаданных.

Мне удалось добавить метаданные на уровне ConventionBuilder с помощью AddPartMetaData:

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 ответ

Поскольку я написал как комментарий, у меня была подобная проблема. После некоторой проработки и ввода кода я получил необходимые метаданные без создания экземпляра типа.

Это мой конфиг 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>).

Другие вопросы по тегам