簡體   English   中英

如何為CQRS的通用對象注冊autofac裝飾器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM