IOC可以摒弃掉类中类的紧耦合,让设计和重用更简单,将IOC加入到MVC中的实现非常简单,那么有哪几种方法?它们的实现又是什么原理呢?
IOC在MVC中的注入,主要是在获取Controller对象中实现,也就是在获取Controller对象的方法中增加注入的相关实现就可以了,这些入口均是在DefaultControllerFactory类中,目前获取Controller的有如下方法:
(1)重写DefaultControllerFactory中的GetControllerInstance方法
源码:
1 protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) 2 { 3 if (controllerType == null) 4 { 5 throw new HttpException(404, 6 String.Format( 7 CultureInfo.CurrentCulture, 8 MvcResources.DefaultControllerFactory_NoControllerFound, 9 requestContext.HttpContext.Request.Path));10 }11 if (!typeof(IController).IsAssignableFrom(controllerType))12 {13 throw new ArgumentException(14 String.Format(15 CultureInfo.CurrentCulture,16 MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase,17 controllerType),18 "controllerType");19 }20 return ControllerActivator.Create(requestContext, controllerType);21 }
重写后:
public class DefaultFactoryIOC:DefaultControllerFactory { private IKernel kernel; public DefaultFactoryIOC() { kernel = new StandardKernel(); kernel.Bind().To (); } protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { return (IController)kernel.TryGet(controllerType); } }Global中定义 ControllerBuilder.Current.SetControllerFactory(new IOCTest.DefaultFactoryIOC());
(2)对前面的方法再一次观察发现,实例化Controller最后是交给了ControllerActivator.Create(requestContext, controllerType)方法,也就是如果能够实现或者重写这个方法就能实现注入,那么ControllerActivator来自于
public DefaultControllerFactory(IControllerActivator controllerActivator) : this(controllerActivator, null, null) { }
接下来实现IControllerActivator这个接口,完成第二种IOC方法
public class ControllerActivatorIOC:IControllerActivator { private IKernel kernel; public ControllerActivatorIOC() { kernel = new StandardKernel(); kernel.Bind().To (); } public IController Create(System.Web.Routing.RequestContext requestContext, Type controllerType) { return (IController)kernel.TryGet(controllerType); } }Global中 protected void Application_Start() { AreaRegistration.RegisterAllAreas(); /*DefaultFactoryController*/ //ControllerBuilder.Current.SetControllerFactory(new IOCTest.DefaultFactoryIOC()); IControllerActivator controlleract = new IOCTest.ControllerActivatorIOC(); DefaultControllerFactory defaultControllerFactory = new DefaultControllerFactory(controlleract); ControllerBuilder.Current.SetControllerFactory(defaultControllerFactory); }
(3)接着最后一个方法仍然是从IControllerActivator 中,再DefaultContollerFactory这个Controller激活类中,默认调用实现IControllerActivator的类是DefaultControllerActivator,
它实现了以上这个Create方法
private Func_resolverThunk; public IController Create(RequestContext requestContext, Type controllerType) { try { return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType)); } catch (Exception ex) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_ErrorCreatingController, controllerType), ex); } }
从上可知,Create方法最后会采用那个默认的构造或者第三方实现_resolverThunk的类来实现,而这个_resolverThunk就是从IDependencyResolver接口而来,所以实现IDependencyResolver就可以达到DI的目的
public class DependencyResolverIOC:IDependencyResolver { private IKernel kernel; public DependencyResolverIOC() { kernel = new StandardKernel(); kernel.Bind().To (); } public object GetService(Type serviceType) { var obj = this.kernel.TryGet(serviceType); return obj; } public IEnumerable
// Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); /*DefaultFactoryController*/ //ControllerBuilder.Current.SetControllerFactory(new IOCTest.DefaultFactoryIOC()); //IControllerActivator controlleract = new IOCTest.ControllerActivatorIOC(); //DefaultControllerFactory defaultControllerFactory = new DefaultControllerFactory(controlleract); //ControllerBuilder.Current.SetControllerFactory(defaultControllerFactory); DependencyResolver.SetResolver(new IOCTest.DependencyResolverIOC()); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); } }