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
が、もう少しエレガントなソリューションを探していました
任意のポインタまたはガイダンスをいただければ幸いです。