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