2017-02-06 71 views
2

語境

的同時努力簡化我們的MediatR代碼,我們爲GETALL,GetSingle,等功能創建通用的請求/響應/處理器的組合。下面你可以找到GETALL實施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() 
      }; 
     } 
    } 
} 

問題

我們似乎無法給我們所有的RequestHandlers一次使用Autofac註冊。

我們能夠利用我們的Autofac模塊註冊一個單一的特定類型的處理程序:

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

但我們願意爲IRequestHandler<,>所有實現(而不僅僅是GETALL之一)這樣做。我們已經嘗試過這種使用AsClosedTypesOf功能如文檔中建議:

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

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

但這個收益率以下異常:

Autofac.Core.Registration.ComponentNotRegisteredException :'請求的服務'MediatR.IRequestHandler<GetAll<T>.Request,GetAll<T>.Response>'尚未註冊。爲避免此異常,請註冊組件以提供服務,使用IsRegistered()檢查服務註冊,或使用ResolveOptional()方法解析可選的依賴項。

我們在這裏做錯了什麼(或忘記)?

+0

也許你可以使用我的結構映射實現。由於我必須指定類型(命令<>,commandHandler <>,query <>,...),所以它遠非完美,但也許可以從這裏開始:https://gist.github。COM/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>.Handler,GetAll<string>.Handler,等等......在它外面
  • 該類型實現的接口是一個泛型? GetAll<T>.Handler implements IRequestHandler<GetAll<T>.Request, GetAll<T>.Response>,這是一個通用類型
  • 最後,是這個接口的通用類型定義IRequestHandler<,>?在我們的例子中,IRequestHandler<GetAll<T>.Request, GetAll<T>.Response>的通用類型定義是IRequestHandler<,>,因此該類型符合必要的標準。

我希望這是有道理的。