在尝试简化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模块中注册一个特定类型的Handler:
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 :(得分: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
实现IRequestHandler<GetAll<T>.Request, GetAll<T>.Response>
,这是一种通用类型IRequestHandler<,>
的泛型类型定义?在我们的例子中,IRequestHandler<GetAll<T>.Request, GetAll<T>.Response>
的泛型类型定义是IRequestHandler<,>
,因此类型符合必要的标准。我希望这是有道理的。