[英]How to register an autofac decorator for a generic object for CQRS
是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有可能吗?
与在ASP.NET Core中使用Autofac注册通用类型的问题有很多共同点
您显示的代码中没有装饰器。
通过使用KeyedService
类键入处理程序的键来注册处理程序时,会KeyedService
。 如果您想让代码正常工作,则有两种解决方案。
最好的选择是不对服务进行加密,因为没有理由-只需查看包含的代码即可对服务进行加密。 您可以注册它们而无需通过以下方式键入它们:
builder
.RegisterAssemblyTypes(assemblies)
.AsClosedTypesOf(typeof(IQueryHandler<,>))
.InstancePerLifetimeScope();
另一种选择是在解析IQueryHandler<TQuery, TResult>
时指示Autofac您正在寻找键服务IQueryHandler<TQuery, TResult>
因为这是您注册它们的方式。 为此,您必须将QueryDispatcher
代码修改为:
var handler = resolver.ResolveKeyed<IQueryHandler<TQuery, TResult>>("QueryHandler");
请不要将传递给ResolveKeyed
方法的密钥与ResolveKeyed
中使用的密钥匹配。 我不知道为什么您会选择第二个选项,但是有可能。
我认为您对装饰家有些困惑。 使用它们需要您对服务进行密钥设置,以便您可以装饰已被密钥化的服务。 请再看一下相关文档 。
Edwok发表评论后进行编辑
对于通用的GetEntitiesQueryHandler<TEntity>
案例,我想说您必须将其注册为开放式通用组件 :
builder
.RegisterGeneric(typeof(GenericEntitiesQueryHandler<>))
.As(typeof(IQueryHandler<,>));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.