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