Я работаю над приложением с использованием MEF (в частности, MEF 2 Preview 5), и у меня возникла проблема с попыткой импорта на основе общих интерфейсов.MEF - ImportMany с общими интерфейсами и Lazy <T, TMetadata>
У меня есть интерфейс:
public interface IMessageHandler<in T>
{
void HandleMessage(T message);
}
, где Т представляет собой тип сообщения, которое будет обрабатываться. Я импортировать эти вещи в каталог с помощью RegistrationBuilder
:
RegistrationBuilder context = new RegistrationBuilder();
context.ForTypesDerivedFrom(typeof(IMessageHandler<>))
.Export(builder => builder.AsContractType(typeof(IMessageHandler<>)));
, а затем, в классе, потребляющего я использую [ImportMany]
импортировать список этих в IEnumerable<Lazy>>
:
[ImportMany(typeof(IMessageHandler<>))]
IEnumerable<Lazy<IMessageHandler<object>, HandledMessageTypeAttribute>> _messageHandlers;
сейчас , здесь первая проблема - вы вынуждены назначать тип для общего интерфейса в этот момент. Я использую Lazy<T, TMetadata>
, поскольку версии IMessageHandler<T>
имеют соответствующие метаданные, которые я хочу использовать (HandledMessageTypeAttribute
).
Теперь, когда я хочу, чтобы получить доступ к любому элементу в IEnumerable<Lazy<>>
коллекции я получаю следующее исключение:
Cannot cast the underlying exported value of type
'MessageHandlerImplementation (ContractName="IMessageHandler(System.Object)")'
to type 'IMessageHandler`1[System.Object]'.
Я понимаю (примерно), почему я получаю исключение, проблема, я понятия не имею, как обойти это. Итак, в основном, что я хочу сделать:
- Имейте кучу классов, которые реализуют интерфейс
IMessageHandler<T>
. - Попросите их обнаружить во время работы с MEF.
- Импортируйте их в коллекцию, которая позволяет мне потреблять любые метаданные, которые у них есть.
- Уметь создавать их.
Я понимаю, что я мог бы просто сделать IMessageHandler
нетипичными и имею IMessageHandler.HandleMessage()
принимает параметр типа object
, но я искал немного более элегантное решение
Любые указатели или инструктивный ценюсь.