Как перечислить все типы, реализующие интерфейс с использованием MEF2? - PullRequest
1 голос
/ 01 октября 2019

Когда я вызываю CompositionHost.GetExport<IInterface>("typename"), я получаю экземпляр запрошенного типа, который реализует IInterface, и все в порядке.

Когда я звоню CompositionHost.GetExports<IInterface>(), я ожидаю список всех типов, которыереализовать IInterface, но в результате получается пустая коллекция.

Либо я неправильно понимаю цель GetExports(), либо я что-то неправильно реализовал.

Мои соглашения построены следующим образом:

conventions.ForTypesDerivedFrom<IInterface>()
           .Export<IInterface>(builder => builder.AsContractName(type => type.Name));

Мои типы реализованы без атрибутов и просто реализуют IInterface.

Есть ли способ составить список типов, используя MEF2, настроенный таким образом? Или мне нужно что-то изменить, чтобы добиться этого?

1 Ответ

1 голос
/ 01 октября 2019

Экспорт описывается экспортными контрактами.

Экспортный контракт - это либо тип, либо тип, объединенный с названием контракта. Используя метод ExportBuilder.AsContractName, вы явно указываете имя контракта. Таким образом, вы можете импортировать эти детали только по типу и имени контракта.

Ваш первый вариант: не указывайте название контракта.

conventions.ForTypesDerivedFrom<IInterface>().Export<IInterface>();

Затем,GetExports<IInterface>() вернет все экземпляры этого типа контракта. Однако вы не сможете импортировать один экземпляр через GetExport<IInterface>(), потому что контейнер сгенерирует исключение, вызванное несколькими известными реализациями.

Кстати, контейнер всегда возвращает экземпляры. Вы пишете, что ожидаете список типов, но вы можете получить только список экземпляров (созданных экземпляров) из контейнера. Чтобы получить список типов, вам нужен каталог, где части управляются. В зависимости от вашей среды у вас может не быть доступа к каталогу.

Если вы все еще хотите иметь обе функции (несколько реализаций и доступ с одной реализацией), рассмотрите возможность перехода от имен контрактов к метаданным.

conventions
    .ForTypesDerivedFrom<IInterface>()
    .Export<IInterface>(builder => builder
        .AsContractType<IInterface>()
        .AddMetadata("ImplementationName", type => type.Name));

var myInstance = container
    .GetExports<Lazy<IInterface, IDictionary<string, object>>>()
    .Where(v => v.Metadata["ImplementationName"] == "YourImplType")
    .FirstOrDefault()?
    .Value;

IDictionary<string, object> - это общее представление метаданных, которое позволяет получить доступ к метаданным деталей.

...