简体   繁体   English

如何为CQRS的通用对象注册autofac装饰器

[英]How to register an autofac decorator for a generic object for CQRS

is the implementations of 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);
    }
}

And I want to create the generic 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 ... 
}

I'm trying to register a generic class as follows: 我正在尝试注册一个通用类,如下所示:

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

And throw error IQueryHandler has not been registered 并抛出错误IQueryHandler尚未注册

Is this possible with Autofac? Autofac有可能吗?

Lots in common with Issue registering generic types with Autofac in ASP.NET Core 与在ASP.NET Core中使用Autofac注册通用类型的问题有很多共同点

There's no decorators in the code you show. 您显示的代码中没有装饰器。

The error you get is expected as you register your handlers by keying them - with the KeyedService class. 通过使用KeyedService键入处理程序的来注册处理程序时,会KeyedService If you want your code to work, you have 2 solutions. 如果您想让代码正常工作,则有两种解决方案。

The best option is to not key your services since there's no reason - again, only looking at the code you included - to key your services. 最好的选择是不对服务进行加密,因为没有理由-只需查看包含的代码即可对服务进行加密。 You can register them without keying them this way: 您可以注册它们而无需通过以下方式键入它们:

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

The other option would be to instruct Autofac you're looking for a keyed service when you resolve the IQueryHandler<TQuery, TResult> since that's how you registered them. 另一种选择是在解析IQueryHandler<TQuery, TResult>时指示Autofac您正在寻找服务IQueryHandler<TQuery, TResult>因为这是您注册它们的方式。 To do so, you'd have to modify your QueryDispatcher code to: 为此,您必须将QueryDispatcher代码修改为:

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

Please not the key passed to the ResolveKeyed method matches the one used in the registration code. 请不要将传递给ResolveKeyed方法的密钥与ResolveKeyed中使用的密钥匹配。 I don't know why you'd choose the second option, but it's possible. 我不知道为什么您会选择第二个选项,但是有可能。

I assume you got a bit confused with decorators . 我认为您对装饰家有些困惑。 Using them requires you to key your services so you can them decorate services that have been keyed . 使用它们需要您对服务进行密钥设置,以便您可以装饰已被密钥化的服务。 Please have another look at the relevant documentation . 请再看一下相关文档

Edit after Edwok's comment Edwok发表评论后进行编辑

For the generic GetEntitiesQueryHandler<TEntity> case, I'd say you have to register it as an open-generic component : 对于通用的GetEntitiesQueryHandler<TEntity>案例,我想说您必须将其注册为开放式通用组件

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM