2017-02-06 2 views
2

コンテキスト

の内部クラスとしてすべてMediatRのハンドラを登録し、我々はGETALL、GetSingle、など。機能のための一般的な要求/応答/ハンドラの組み合わせを作成しました。以下は、私たちがかつてAutofacを使用してのすべての私たちRequestHandlersを登録することができないようAutofacは:私たちのMediatRコードを簡素化しようとしますが、一般的なタイプの

public class GetAll<T> where T : class 
{ 
    public class Request : IRequest<Response> 
    { 
    } 

    public class Response 
    { 
     public IQueryable<T> All { get; set; } 
    } 

    public class Handler : IRequestHandler<Request, Response> 
    { 
     private readonly IRepository<T> repository; 

     public Handler(IRepository<T> repository) 
     { 
      this.repository = repository; 
     } 

     public Response Handle(Request message) 
     { 
      return new Response 
      { 
       All = repository.GetAll() 
      }; 
     } 
    } 
} 

問題

GETALLの実装を見つけることができます。

私たちが使用して私たちのAutofacモジュールにおけるハンドラの単一の特定のタイプを登録することができます:

builder.RegisterGeneric(typeof(GetAll<>.Handler)).AsImplementedInterfaces(); 

をしかし、我々はすべてIRequestHandler<,>の実装(だけでなくGETALL 1)のためにこれをやりたいです。

builder.RegisterAssemblyTypes(typeof(GetAll<>.Request).Assembly) 
       .AsClosedTypesOf(typeof(IRequestHandler<,>)); 

または

builder.RegisterAssemblyTypes(typeof(GetAll<>.Request).Assembly) 
       .AsClosedTypesOf(typeof(IRequestHandler<,>)) 
       .AsImplementedInterfaces(); 

しかし、この利回り次の例外:

Autofac.Core.Registration.ComponentNotRegisteredException文書で提案されているように私たちはAsClosedTypesOf機能を使って、これを試してみました: '要求されたサービス'MediatR.IRequestHandler<GetAll<T>.Request,GetAll<T>.Response>'は登録されていません。この例外を回避するには、サービスを提供するコンポーネントを登録するか、IsRegistered()を使用してサービス登録を確認するか、ResolveOptional()メソッドを使用してオプションの依存関係を解決してください。

ここで間違っている(または忘れている)のは何ですか?

+0

おそらく私の構造マップ実装を使用することができます。私は型(command <>、commandHandler <>、query <>、...)を指定しなければならないので、完璧ではありませんでしたが、おそらくそこから始めることができます:https://gist.github。co.jp/hudo/0e9fb466c3fac5a04aa1b77cc95490e5 –

答えて

1

あなたが言及したように、それらをジェネリックとして登録する必要があるため、一度に登録することはできません。しかし、あなたは反射のビットは、このようなハンドラのリストを維持する手動避けるための方法があります:

var genericRequestHandlers = typeof(GetAll<>).Assembly 
    .ExportedTypes 
    .Where(x => IsGenericRequestHandler(x)) 
    .ToArray(); 

foreach (var genericRequestHandler in genericRequestHandlers) 
{ 
    builder 
     .RegisterGeneric(genericRequestHandler) 
     .AsImplementedInterfaces(); 
} 

private static bool IsGenericRequestHandler(Type t) 
{ 
    return 
     t.IsGenericTypeDefinition && 
     t.GetInterfaces.Any(i => 
     { 
      return 
       i.IsGenericType && 
       i.GetGenericTypeDefinition == typeof(IRequestHandler<,>); 
     }); 
} 

ここIsGenericRequestHandlerで行わチェックの説明です:

  • は、一般的なタイプです型定義ですか?言い換えれば、この型定義からジェネリック型を構築することができますか? GetAll<T>.HandlerはあなたがGetAll<int>.HandlerGetAll<string>.Handlerなどを構築することができますので、そのうちから
  • タイプは汎用タイプのインターフェースを実装していますか? GetAll<T>.Handlerは汎用タイプであるIRequestHandler<GetAll<T>.Request, GetAll<T>.Response>を実装します
  • 最後に、このインターフェイスの汎用タイプの定義はIRequestHandler<,>ですか?私たちの場合、IRequestHandler<GetAll<T>.Request, GetAll<T>.Response>のジェネリック型定義はIRequestHandler<,>であるため、型は必要な基準と一致します。

これは意味があると思います。

関連する問題