Как зарегистрировать автофакторный декоратор для универсального объекта для 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?

1 ответ

Решение

Много общего с проблемой регистрации общих типов с помощью Autofac в ASP.NET Core

В показанном вами коде нет декораторов.

Полученная ошибка ожидается, когда вы регистрируете свои обработчики, набирая их - с помощью KeyedService учебный класс. Если вы хотите, чтобы ваш код работал, у вас есть 2 решения.

Лучший вариант - не указывать свои услуги, поскольку нет никаких причин - опять же, только смотреть на код, который вы включили - чтобы обозначить свои услуги. Вы можете зарегистрировать их, не набирая их так:

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

Другой вариант - указать Autofac, что вы ищете службу с ключами, при разрешении IQueryHandler<TQuery, TResult> так как ты их так зарегистрировал. Для этого вам придется изменить ваш QueryDispatcher код для:

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

Пожалуйста, не передавайте ключ ResolveKeyed Метод соответствует тому, который используется в регистрационном коде. Я не знаю, почему вы выбрали бы второй вариант, но это возможно.

Я полагаю, вы немного запутались с декораторами. Их использование требует от вас указания ключей ваших служб, чтобы вы могли украсить службы, которые были введены. Пожалуйста, посмотрите еще раз на соответствующую документацию.

Редактировать после комментария Эдвок

Для общего GetEntitiesQueryHandler<TEntity> В этом случае я бы сказал, что вы должны зарегистрировать его как компонент общего назначения:

builder
    .RegisterGeneric(typeof(GenericEntitiesQueryHandler<>))
    .As(typeof(IQueryHandler<,>));
Другие вопросы по тегам