2017-05-17 102 views
1

我正在編寫一個應用程序,它針對不同的客戶端具有不同的類實現。我們正在使用CQRS,並且我想爲每個客戶端添加不同的命令和查詢實現(如果沒有客戶端特定的客戶端,則默認爲默認值)。基於屬性的Unity容器解析

該應用程序以前編寫只有一個客戶端,這工作正常,但現在我們需要重寫爲每個客戶端的命令和客戶端。我已經提出了許多關於如何做到這一點的想法,但這種感覺最清晰,因爲只需添加一組查詢/命令即可輕鬆添加新客戶端。

調度該查詢的代碼如下:

public InProcQueryDispatcher(
     IQueryHandlerFactory queryHandlerFactory, 
     Action<Exception, IQuery> onHandlerFailed) 
    { 
     this.queryHandlerFactory = queryHandlerFactory; 
     this.onHandlerFailed = onHandlerFailed; 
     this.getHandlerMethod = typeof(IQueryHandlerFactory).GetMethod("GetHandler"); 
    } 

    public async Task<TResult> Execute<TResult>(IQuery<TResult> query) 
    { 
     if (query == null) 
     { 
      throw new ArgumentNullException(); 
     } 

     try 
     { 
      var queryHandler = this.ResolveHandler<TResult>(query.GetType()); 

      var task = (Task<TResult>) queryHandler.Handle((dynamic) query); 

      return await task; 
     } 
     catch (Exception ex) 
     { 
      this.onHandlerFailed(ex, query); 
      throw; 
     } 
    } 

    private dynamic ResolveHandler<TResult>(Type queryType) 
    { 
     var getHandler = this.getHandlerMethod.MakeGenericMethod(queryType, typeof (TResult)); 
     return getHandler.Invoke(this.queryHandlerFactory, null); 
    } 
} 

我現在希望能夠改變它,如下所示:

`public async Task<TResult> Execute<TResult>(IQuery<TResult> query) 
     { 
      if (query == null) 
      { 
       throw new ArgumentNullException(); 
      } 

      try 
      { 
       var queryHandler = this.ResolveHandler<TResult>(query.GetType(), query.ClientId); 

       var task = (Task<TResult>) queryHandler.Handle((dynamic) query); 

       return await task; 
      } 
      catch (Exception ex) 
      { 
       this.onHandlerFailed(ex, query); 
       throw; 
      } 
     } 

     private dynamic ResolveHandler<TResult>(Type queryType, Guid clientId) 
     { 
      var getHandler = this.getHandlerMethod.MakeGenericMethod(queryType, clientId, typeof (TResult)); 
      return getHandler.Invoke(this.queryHandlerFactory, null); 
     } 

誰能推薦我怎麼可以更新我的getHandleMethod解決基於clientID的正確查詢?

GetHandleMethod:

public IQueryHandler<TQuery, TResult> GetHandler<TQuery, TResult>() where TQuery : class, IQuery<TResult> 
    { 
     return container.Resolve<IQueryHandler<TQuery, TResult>>(); 
    } 

回答

0

使用IoC,,你的對象不應該是容器本身的知道,在你有權不容器直接傳遞給構造函數的意義。但是,您可以將工廠傳遞給您的班級,然後用它來解決。我發現將它與命名註冊結合起來效果很好。你如何能做到這一點的總結是沿着線的東西:

container.RegisterType<IQueryHandler<TQuery, TResult>, QueryHandlerVersionOne<TQuery, TResult>>("1"); 
container.RegisterType<IQueryHandler<TQuery, TResult>, QueryHandlerVersionTwo<TQuery, TResult>>("2"); 

container.RegisterType<Func<int, IQueryHandler<TQuery, TResult>>>(
    new InjectionFactory(c => 
     new Func<int, IQueryHandler<TQuery, TResult>>((clientID) => 
     { 
      var handler = c.Resolve<IQueryHandler<TQuery, TResult>>(clientID.ToString()); 

      return handler; 
     }))); 

,然後在你的構造函數,你添加參數爲工廠注入Func<int, IQueryHandler<TQuery, TResult>>類型。

我回答了一個更長的例子in this post