1

我有一個MVC應用程序,我正在實現CQRS,其中我將讀取數據的數據分離爲單獨的接口。我正在使用構造函數注入將這些接口的具體實例注入到Controller中。對於構造函數注入,我使用Unity容器。見例如MVC:有條件地調用重載的構造函數

//The Employee controller 
public class EmployeeController : Controller 
{ 
    IEmployeeRepository _Writer; 

    IEmployeeQuery _Reader; 

    //constructor injection 
    public EmployeeController(IEmployeeRepository writer, IEmployeeQuery reader) 
    { 
     this._Writer = writer; 
    this._Reader = reader; 

    } 


    //To Do: constructor injection for write operations only 
    public EmployeeController(IEmployeeRepository writer) 
    { 
     this._Writer = writer; 

    } 

    //To Do: constructor injection for read operations only 
    public EmployeeController(IEmployeeQuery reader) 
    { 
     this._Reader = reader; 

    } 
} 


//Registration of the concrete types in the unity container. 
public static class Bootstrapper 
{ 
    public static void ConfigureUnityContainer() 
    { 
     IUnityContainer container = new UnityContainer(); 

     container.RegisterType<IEmployeeRepository, EmployeeRepository>(new HttpContextLifetimeManager<IEmployeeRepository>()); 
     container.RegisterType<IEmployeeQuery, EmployeeQueries>(new HttpContextLifetimeManager<IEmployeeQuery>()); 
     ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container)); 
    } 
} 

//The derived Controller Factory for injection dependencies in the Controller constructor 
public class UnityControllerFactory : DefaultControllerFactory 
{ 
    IUnityContainer container; 

    public UnityControllerFactory(IUnityContainer container) 
    { 
     this.container = container; 
    } 
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 


     try 
     { 
      if (controllerType == null) 
      { 
       throw new ArgumentNullException("controllerType"); 
      } 

      if (!typeof(IController).IsAssignableFrom(controllerType)) 
      { 
       throw new ArgumentException(String.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType"); 
      } 

      return container.Resolve(controllerType) as IController; 





     } 
     catch (Exception) 
     { 

      return null; 
     } 
    } 
} 

我已經想通了,任何行動,我將要麼被讀取或寫入數據但不能同時下方。在這種情況下,我需要根據需要初始化哪一個「_Writer」或「_Reader」來有條件地調用控制器構造函數。

這怎麼辦?

回答

1

看起來你有一個控制器,你應該使用兩個?如果你永遠不需要能夠讀寫,我會考慮重構這個組件來承擔單一的責任。

如果你不想這樣做,我會考慮注入一個NullObject,而不是注入那個依賴關係。見this thread

TecX project包含一個模仿NInject的上下文綁定的擴展。這將允許您指定何時注入什麼依賴關係。該代碼可在TecX.Unity項目(文件夾ContextualBinding)中找到。顯示如何使用它的測試在TecX.Unity.ContextualBinding.Test項目中)。

+0

@@塞巴斯蒂安,我還沒有看到有多個控制器在Web應用程序中使用相同的視圖在實踐中,雖然在理論上似乎可行的。你能告訴我一個如何實現這個目標的例子嗎?在嘗試其他選擇之前,我寧願選擇單一責任的概念正確選項。 – devanalyst 2012-07-17 04:34:27

+0

@devanalyst我不是MVC的專家。這些是我認爲適用於任何類型架構的準則。如果您有兩個單獨工作的獨立部分 - 不要試圖將它們放在同一個類中(通常)違反SRP。當你只是讀或寫時,它是否真的是一樣的觀點?如果是這樣,你可以同時執行兩個操作(讀取和寫入) - 是否真的不需要執行這兩個操作?僅注入閱讀器或書寫器是否值得努力?只是一些想法。 – 2012-07-17 06:52:38

+0

@devanalyst你是對的!通常情況下,對於同一個視圖,有多個控制器是不正確的。相反,您在多個CRUD操作的同一控制器類中有多個方法(MVC範例中的Actions)。儘管每次都要注入依賴項,而不管它們是否被使用。當你配置你的DI容器時,你可以簡單地告訴他們實現特定接口的類的名字。如果存在多個重載的構造函數,則不能將它們配置爲調用特定的構造函數來創建實現的實例。 – RBT 2016-03-15 00:28:24