主要概念:
注:以下概念是自我理解,不是很准确。
- IOC:Inversion of Control(控制反转)。
本来对象创建是通过使用类内部进行创建,现在把对象创建交给container(容器)管理
打个比方好比现在华数网络(container),你去华数网络营业厅注册服务(普通电视,高清电视,华数网络),等你回家你接上电视,华数网络(container)就可以将普通电视或高清电视的对象返回给你;当你接上电脑时,华数网络(container)就将华数网络对象返回给你。
- Unity
Unity是微软的一款轻量级的容器。
namespace MVCIOC.IOC { public class HttpContainerBuilder { public static readonly IUnityContainer UnityContainer = new UnityContainer(); public static void Register() { //注册Service1和Service2 UnityContainer.RegisterType(typeof (Service1)); UnityContainer.RegisterType(typeof (Service2)); //注册Control UnityContainer.RegisterType(typeof (HomeController)); } } }
这个往UnityContainer中注册了两个Servie1和Service2两种类型,并注册了HomeController
namespace MVCIOC.IOC { public class UnityDependencyResolver : IDependencyResolver { IUnityContainer container; public UnityDependencyResolver(IUnityContainer UnityContainer) { this.container = UnityContainer; } public object GetService(Type serviceType) { return container.Resolve(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return container.ResolveAll(serviceType); } } }
IDependencyResolver是依赖解析器接口
protected void Application_Start() { HttpContainerBuilder.Register(); DependencyResolver.SetResolver(new UnityDependencyResolver(HttpContainerBuilder.UnityContainer)); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
注册类型,并设置依赖解析器(实现IDependencyResover接口的对象),这样UnityDependencyResolver接管了部分依赖注入类
这样理论上里说,Sevice1,Service2,HomeControl类创建类型由Container容器来创建,感觉IOC与MVC已经完美结合了,但是运行以后就碰到了阻力。
缺少一个IControllerFactory类,缺少类型映射。
正如dudu所说我们总不能MVC中的所有接口都要注册一下,所以我们需要知道什么时候接受创建Controller,当Contorller所有准备都完成后,我们才接受创建Controller
public class UnityControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { return (IController)HttpContainerBuilder.UnityContainer.Resolve(controllerType); } }
这样我们在获取Controller时才从容器中解析对象,但是我们如果将那些没有在容器中注册过的类,实例化交给MVC自己实例
public object GetService(Type serviceType) { if (container.IsRegistered(serviceType)) { return container.Resolve(serviceType); } return null; }
当依赖解析器发现此类型没有注册过,就返回null,这样此类型的实例还有默认实例方式进行实例。
综上就可以将IOC与MVC完美结合了,总结如下:
1.UnityContainner 通过方法RegisterType(Type) 注册类型
2.UnityDependecyResolver:IDenpendecySolve
定义依赖解析的方式,可以指定给MVC
3.DependencyResolver.setResolver(第二点对象) 设置MVC依赖解析器
4.GetService(Type type)
获取解析对象,判断类型是否已注册 containner.IsRegistered(Type type),若没有注册,就返回null,还是采用默认获取对象方式
5.UnityControllerFactory:DefaultControllerFactory
重写GetControllerInstance(),将其从容器中获取对象
如何保证容器中在一次Http请求中保证只有一个对象,所以要LifetimeManager(生命周期策略)
这个下次再讲。
- Autofac(推荐)
Autofac在使用中发现,他比Unity更贴切MVC
下载地址:http://code.google.com/p/autofac/downloads/list
Autofac.dll 基础包
Autofac.Integration.Mvc.dll MVC包
//注册数据库访问对象 ContainerBuilder.RegisterType(contextType).InstancePerHttpRequest(); //注册Service对象 ContainerBuilder.RegisterAssemblyTypes(serviceAssembly).InstancePerHttpRequest(); //注册仓储类 ContainerBuilder.RegisterAssemblyTypes(repositoryAssembly).InstancePerHttpRequest(); //注册Mvc控制器 ContainerBuilder.RegisterControllers(webAssembly).InstancePerHttpRequest(); //注册Mvc模型绑定管道 ContainerBuilder.RegisterModelBinderProvider(); //注册Mvc模型绑定器 ContainerBuilder.RegisterModelBinders(); Container = ContainerBuilder.Build(); //Contoler的MVC解析点通过Container DependencyResolver.SetResolver(new AutofacDependencyResolver(Container));
InstancePerHttpRequest:保证了生命周期策略,每次Http请求只实例化一次
RegisterControllers:提供了单独注册Controller的方法