是CQRS的实现:
public interface IQuery<TResult> {}
public interface IQueryHandler<in TQuery, TResult>
where TQuery : IQuery<TResult>
{
Task<TResult> HandleAsync(TQuery query);
}
public interface IQueryDispatcher
{
Task<TResult> DispatchAsync<TQuery, TResult>(TQuery query)
where TQuery : IQuery<TResult>;
}
public class QueryDispatcher : IQueryDispatcher
{
private readonly IComponentContext resolver;
public QueryDispatcher(IComponentContext resolver)
{
if (resolver == null)
{
throw new ArgumentNullException(nameof(resolver));
}
this.resolver = resolver;
}
public async Task<TResult> DispatchAsync<TQuery, TResult>(TQuery query)
where TQuery : IQuery<TResult>
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
var handler = resolver.Resolve<IQueryHandler<TQuery, TResult>>();
return await handler.HandleAsync(query);
}
}
我想创建通用查询:
public class GetEntitiesQuery<TEntity> : IQuery<IQueryable<TEntity>>
where TEntity : Entity
{
}
public class GetEntitiesQueryHandler<TEntity> : IQueryHandler<GetEntitiesQuery<TEntity>, IQueryable<TEntity>>
where TEntity : Entity
{
// this code ...
}
我正在尝试注册一个泛型类,如下所示:
builder.RegisterType<QueryDispatcher>().As<IQueryDispatcher>().InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(assemblies)
.As(type => type.GetInterfaces()
.Where(interfaceType => interfaceType.IsClosedTypeOf(typeof(IQueryHandler<,>)))
.Select(interfaceType => new KeyedService("QueryHandler", interfaceType)))
.InstancePerLifetimeScope();
抛出错误IQueryHandler尚未注册
这可以用Autofac吗?
答案 0 :(得分:0)
与Issue registering generic types with Autofac in ASP.NET Core
有很多共同之处您显示的代码中没有装饰器。
当您通过键入来注册处理程序时,您会得到错误 - 使用KeyedService
类。如果您希望代码有效,那么您有两种解决方案。
最好的选择是不对您的服务进行密钥管理,因为没有理由 - 再次只查看您包含的代码 - 来修改您的服务。您可以通过以下方式注册键入:
builder
.RegisterAssemblyTypes(assemblies)
.AsClosedTypesOf(typeof(IQueryHandler<,>))
.InstancePerLifetimeScope();
另一种选择是在解析IQueryHandler<TQuery, TResult>
时指示Autofac您正在寻找键控服务,因为这是您注册它们的方式。为此,您必须将QueryDispatcher
代码修改为:
var handler = resolver.ResolveKeyed<IQueryHandler<TQuery, TResult>>("QueryHandler");
请不要传递给ResolveKeyed
方法的密钥与注册代码中使用的密钥匹配。我不知道你为什么选择第二种选择,但这是可能的。
我认为你对decorators感到困惑。使用它们需要您键入您的服务,以便您可以装饰已经键入的服务。请再看一下the relevant documentation。
Edwok评论后编辑
对于通用GetEntitiesQueryHandler<TEntity>
案例,我要说你必须将其注册为open-generic component:
builder
.RegisterGeneric(typeof(GenericEntitiesQueryHandler<>))
.As(typeof(IQueryHandler<,>));