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. Но большинство из них работают с необщим экспортом, что не является моей целью.


person SBeltz    schedule 24.07.2014    source источник
comment
Я столкнулся с той же проблемой при создании MVC ControllerFactory. Вы уже нашли какое-нибудь решение?   -  person Andreas    schedule 14.08.2014
comment
@Andreas до сих пор нет ответа ... Я также разместил это на форуме разработчиков приложений MSDN. Они тоже не смогли мне помочь и предложили опубликовать вопрос на форуме MEF в центре разработчиков MSDN Silverlight. Поскольку самый последний пост там датируется декабрем 2013 года, я решил пока оставить свою реализацию MEF1. Пожалуйста, дайте мне знать, когда вы найдете какое-либо жизнеспособное решение. Спасибо!   -  person SBeltz    schedule 18.08.2014


Ответы (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>).

person Andreas    schedule 20.08.2014