MEF (具体的にはMEF 2 Preview 5 )を使用するアプリケーションに取り組んでおり、汎用インターフェイスに基づいてインポートしようとすると問題が発生しました。
私はインターフェースを持っています:
public interface IMessageHandler<in T>
{
void HandleMessage(T message);
}
ここで、T は処理するメッセージのタイプです。以下を使用して、これらのものをカタログにインポートしてい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が、もう少しエレガントなソリューションを探していました
任意のポインタまたはガイダンスをいただければ幸いです。