2017-02-06 72 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<,>,因此该类型符合必要的标准。

我希望这是有道理的。