MVC:有条件地调用重载的构造函数

时间:2012-07-16 11:26:31

标签: asp.net-mvc-3 dependency-injection unity-container cqrs constructor-injection

我有一个MVC应用程序,我正在实施CQRS,我将已保存的数据从读取数据分离到单独的接口。我正在使用构造函数注入将这些接口的具体实例注入Controller。对于构造函数注入,我使用的是Unity容器。见下面的例子

//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;
        }
    }
}

我已经发现,对于任何操作,我将获取数据或写入数据,但不是两者。在这种情况下,我需要有条件地调用控制器构造函数,具体取决于&#34; _Writer&#34;或&#34; _Reader&#34;我需要初始化。

如何做到这一点?

2 个答案:

答案 0 :(得分:1)

看起来你有一个控制器,你应该使用两个?如果您永远不需要能够同时阅读和写作,我会考虑将该组件重构为单一责任。

如果您不想这样做,我会考虑注入NullObject而不是根本不注入该依赖项。请参阅this thread

TecX project包含一个模仿NInject上下文绑定的扩展。这将允许您指定何时注入什么依赖项。代码可以在 TecX.Unity 项目(文件夹 ContextualBinding )中找到。显示如何使用它的测试位于 TecX.Unity.ContextualBinding.Test 项目中。

答案 1 :(得分:1)

延迟加载组件怎么样?您解决了两个依赖关系,但只初始化了一个真正使用的依赖关系。

此处示例:http://pwlodek.blogspot.com/2010/05/lazy-and-ienumerable-support-comes-to.html