如何为CQRS的通用对象注册AutoFac Decorator



是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类中注册处理程序时,您会收到的错误。如果您希望代码工作,则有2个解决方案。

最好的选择是不要键入您的服务,因为没有理由 - 同样,只查看您包括的代码 - 键入服务。您可以以这种方式注册它们,而无需键盘

builder
    .RegisterAssemblyTypes(assemblies)
    .AsClosedTypesOf(typeof(IQueryHandler<,>))
    .InstancePerLifetimeScope();

另一个选项是指示您在解决IQueryHandler<TQuery, TResult>时正在寻找A 键控服务,因为这是您注册它们的方式。为此,您必须将QueryDispatcher代码修改为:

var handler = resolver.ResolveKeyed<IQueryHandler<TQuery, TResult>>("QueryHandler");

请不要传递给ResolveKeyed方法的密钥与注册代码中使用的密钥匹配。我不知道为什么您会选择第二个选项,但可能会。

我认为您与装饰师有点混淆。使用它们需要您键入服务,以便您可以装饰已键入的服务。请再次查看相关文档。

Edwok的评论后编辑

对于通用GetEntitiesQueryHandler<TEntity>情况,我要说您必须将其注册为开放式组件:

builder
    .RegisterGeneric(typeof(GenericEntitiesQueryHandler<>))
    .As(typeof(IQueryHandler<,>));

最新更新