2016-12-15 48 views
0

的通用對象的autofac裝飾是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可以嗎?

回答

0

很多共同點Issue registering generic types with Autofac in 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方法的關鍵匹配在註冊代碼中使用的一個。我不知道你爲什麼選擇第二種選擇,但這是可能的。

我假設你對decorators有點困惑。使用它們需要您輸入服務的密鑰,以便他們可以修飾已被鍵入的服務。請再看看the relevant documentation。後

編輯Edwok的評論

對於通用GetEntitiesQueryHandler<TEntity>情況下,我會說你必須將其註冊爲一個open-generic component

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

不要工作這兩種解決方案。也許是GetEntitiesQueryHandler 和GetEntitiesQuery '半封閉'泛型組件,試圖註冊裝飾器,不起作用。 – Edwok

+0

http://stackoverflow.com/questions/27509729/registering-half-closed-generic-component – Edwok

+0

如何與Autofac? – Edwok