使用Spring.Net 1.3.2实现Container(IoC)(二)ASP.NET MVC、ControllerFactory

mac2022-06-30  21

ControllerFactory

ControllerFactory是基于路由的组件,它选择正确的controller并对其实例化。default factory会查找实现了IController并且以Controller结尾的类,然后通过反射使用无参构造函数进行实例化。

但如果您希望使用依赖注入,就不能再使用default factory,而必须使用支持IoC的controller factory。

使用支持IoC(依赖注入)的controller factory, 优点在于松耦合,可测试性很好。如果在Controller里面想要使用某些Service,要么new出来,要么用单例的形式,如UserService.Instance,这样想对Controller写单元测试都不容易,它和这些Service耦合太紧密,无法将这些Service替换成Stub实现。因此,松耦合是必须的。要实现这个功能,必须让依赖注入框架来创建Controller,才有可能注入依赖并组装对象。MVC里面有一个ControllerFactory的东西,可以使用来达到这个目的。

方法:

1、写一个类,继承自DefaultControllerFactory,例如 SpringControllerFactory : DefaultControllerFactory2、覆盖方法GetControllerInstance,使用依赖注入框架来创建Conroller3、修改Global.asax.cs, 在Application_Start内注册使用自己的ControllerFactory,

ControllerBuilder.Current.SetControllerFactory(new SpringControllerFactory())

4、对Controller进行构造函数注入,例如:

public class AccountController : Controller {private IRepository repository;public IRepository Repository {get {return repository; }set { repository = value; } } }

从现在开始,所有的Controller都是通过依赖注入框架来创建的,新增的Service就在依赖注入框架里面注册,Controller要使用哪些Service就往构造函数里加,反正框架会注入进来。 

MVCQuick的ControllerFactory

在“使用Spring.Net 1.3.2实现Container(IoC)(一)”已使用Spring.NET实现了一个简单的IoC容器ClassicContainer,故实现支持IoC的ControllerFactory手到擒来。 

MVCQuick的ControllerFactory实现代码

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;using System.Collections;using MVCQuick.Framework.Container;namespace MVCQuick.Framework.Mvc{public class ClassicControllerFactory : DefaultControllerFactory { public override IController CreateController(RequestContext requestContext, string controllerName) { IController controller = ClassicContainer.GetObject(controllerName) as IController;if (controller == null) { controller = base.CreateController(requestContext, controllerName); } AddActionInvokerTo(controller);return controller; }protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { IController controller = null;if (controllerType != null) { var controllers = ClassicContainer.GetObjects(controllerType);if (controllers.Count > 0) { controller = (IController)controllers.Cast<DictionaryEntry>().First().Value; } }else { controller = base.GetControllerInstance(requestContext, controllerType); } AddActionInvokerTo(controller);return controller; }protected virtual void AddActionInvokerTo(IController controller) {if (controller == null)return;if (typeof(Controller).IsAssignableFrom(controller.GetType())) { ((Controller)controller).ActionInvoker = new ClassicActionInvoker(); } } }} using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using MVCQuick.Framework.Container;namespace MVCQuick.Framework.Mvc{///<summary>/// ActionInvoker implementation that enables the <see cref="IApplicationContext"/>to satisfy dependencies on ActionFilter attributes.///</summary> public class ClassicActionInvoker : ControllerActionInvoker {///<summary>/// ///</summary> public ClassicActionInvoker() { }///<summary>/// Retrieves information about the action filters.///</summary>///<param name="controllerContext">The controller context.</param>///<param name="actionDescriptor">The action descriptor.</param>///<returns>Information about the action filters.</returns> protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {//let the base class do the actual work as usual var filterInfo = base.GetFilters(controllerContext, actionDescriptor);//configure each collection of filters using the IApplicationContext foreach (IActionFilter filter in filterInfo.ActionFilters.Where(f => f != null)) { ClassicContainer.ConfigureObject(filter, filter.GetType().FullName); }foreach (IAuthorizationFilter filter in filterInfo.AuthorizationFilters.Where(f => f != null)) { ClassicContainer.ConfigureObject(filter, filter.GetType().FullName); }foreach (IExceptionFilter filter in filterInfo.ExceptionFilters.Where(f => f != null)) { ClassicContainer.ConfigureObject(filter, filter.GetType().FullName); }foreach (IResultFilter filter in filterInfo.ResultFilters.Where(f => f != null)) { ClassicContainer.ConfigureObject(filter, filter.GetType().FullName); }return filterInfo; } }}

 

ClassicControllerFactory使用方法

在Global.asax.cs类Application_Start()添加代码

//Register RepositoryClassicContainer.Register<NHibernateRepository>("NHibernateRepository"); //Register ControllerIDictionary properties = new Dictionary<String, Object>();properties.Add("Repository", ClassicContainer.GetObject("NHibernateRepository"));ClassicContainer.Register<AccountController>("Account", properties);ClassicContainer.Register<CheckoutController>("Checkout", properties);ClassicContainer.Register<HomeController>("Home", properties);ClassicContainer.Register<ShoppingCartController>("ShoppingCart", properties);ClassicContainer.Register<StoreController>("Store", properties);ClassicContainer.Register<StoreManagerController>("StoreManager", properties);ClassicContainer.Register<SampleDataController>("SampleData", properties); //Set ControllerFactoryControllerBuilder.Current.SetControllerFactory(typeof(ClassicControllerFactory));

 

源代码下载:http://mvcquick.codeplex.com/  

转载于:https://www.cnblogs.com/guyoung/archive/2011/10/16/2214388.html

相关资源:Spring.net 中文帮助文档 第二版
最新回复(0)