2

语境

在尝试简化 MediatR 代码的同时,我们为 GetAll、GetSingle 等功能创建了通用的请求/响应/处理程序组合。您可以在下面找到 GetAll 实现

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()
            };
        }
    }
}

问题

我们似乎无法使用 Autofac 一次注册所有的 RequestHandler。

我们可以使用以下方法在 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() 方法解决可选依赖项。

我们在这里做错了什么(或忘记了)?

4

1 回答 1

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>.Handlerimplements IRequestHandler<GetAll<T>.Request, GetAll<T>.Response>,这是一个泛型类型
  • 最后,是这个接口的泛型类型定义IRequestHandler<,>吗?IRequestHandler<GetAll<T>.Request, GetAll<T>.Response>在我们的例子中, is的泛型类型定义IRequestHandler<,>使得该类型符合必要的标准。

我希望这是有道理的。

于 2017-02-06T22:11:00.590 回答