也许你会问ASP.NET MVC为什么会爱上IoC?
创新互联-专业网站定制、快速模板网站建设、高性价比华池网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式华池网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖华池地区。费用合理售后完善,10多年实体公司更值得信赖。
相爱的理由常常很简单,就像一首歌中所唱——“只为相遇那一个眼神”。
而ASP.NET MVC爱上IoC只为IoC能实现MVC控制器的依赖注入。
下面是一个网站所用的一个MVC控制器:
public class EnterpriseController { protected IJobService _jobService; protected IEnterpriseService _enterpriseService; #region Constructors public EnterpriseController(IJobService jobService, IEnterpriseService enterpriseService) { _jobService = jobService; _enterpriseService = enterpriseService; } #endregion }
如上面的代码所示,有了IoC进行依赖注入,就不需要在构造函数中专门创建对应于_jobService与_enterpriseService的实例。IoC容器会在运行时自动创建IJobService与IEnterpriseService的实例,并传递给EnterpriseController的构造函数。
就因为这一点,MVC就爱上了IoC。爱就这么简单。
但是相爱容易,相处难。。。相处的过程中总会遇到各种各样的问题。。。所以幸福来自于你是否能努力解决这些问题。
代码世界也一样,当我们让MVC与IoC相处时,就遇到了问题。这里我们以IoC容器Unity为例,说明一下我们遇到的问题与解决方法。
要想实现Controller的依赖注入,就需要让IoC容器接管Controller的创建,而ASP.NET MVC 3中提供的IDependencyResolver接口就为实现这个提供了可能。所以,我们首先创建一个实现IDependencyResolver接口的UnityDependencyResolver类,代码如下:
public class UnityDependencyResolver : IDependencyResolver { IUnityContainer container; public UnityDependencyResolver(IUnityContainer container) { this.container = container; } public object GetService(Type serviceType) { return container.Resolve(serviceType); } public IEnumerable GetServices(Type serviceType) { return container.ResolveAll(serviceType); } } UnityDependencyResolver的作用就是调用IoC容器(这里是Unity)解析相应类型的实例。创建了UnityDependencyResolver,我们还需要告诉MVC用它进行解析。在Global.asax的Application_Start()方法中添加如下代码: protected void Application_Start() { IUnityContainer container = new UnityContainer(); DependencyResolver.SetResolver(new UnityDependencyResolver(container)); } 我们运行一下程序试试,出现下面的错误提示:The current type, System.Web.Mvc.IControllerFactory, is an interface and cannot be constructed. Are you missing a type mapping?从上面的错误信息可以分析出,错误是发生在调用UnityDependencyResolver.GetService方法时。ASP.NET MVC在运行的时候需要得到IControllerFactory的实现实例,然后用它去创建相应的控制器实例。如果不用IoC容器,MVC默认会创建DefaultControllerFactory的实例。现在用了IoC,MVC找不到IControllerFactory的实现实例(我们根本没有注册嘛),所以出现上面的错误。为了解决这个问题,我们注册一下DefaultControllerFactory: container.RegisterType(); 继续运行程序,又出现新的错误:The current type, System.Web.Mvc.IControllerActivator, is an interface and cannot be constructed. Are you missing a type mapping?找不到IControllerActivator的实现实例,看来,创建Controller还需要这个东东。查看MVC的源代码发现IControllerActivator的默认实现是DefaultControllerActivator,但郁闷的是它竟然是private class,无法注册它。别无选择,只能自己实现IControllerActivator,名叫CustomControllerActivator,代码如下: public class CustomControllerActivator : IControllerActivator { IController IControllerActivator.Create( System.Web.Routing.RequestContext requestContext, Type controllerType) { return DependencyResolver.Current .GetService(controllerType) as IController; } } 继续运行,又出现新的错误:The current type, System.Web.Mvc.IViewPageActivator, is an interface and cannot be constructed. Are you missing a type mapping?天哪!难道MVC中的所有接口都要注册一下。。。这时,脑子里突然闪出一个指示牌:[[40973]] 于是,脚踩刹车,打了一把方向盘,驶上了另一条道 —— 如果IoC容器中没有注册,不引发异常,而是返回null,让MVC用自己的方式去处理。修改UnityDependencyResolver的GetService方法: public object GetService(Type serviceType) { if (!this.container.IsRegistered(serviceType)) { return null; } return container.Resolve(serviceType); } 并取消之前在IoC容器中对DefaultControllerFactory与CustomControllerActivator的注册。继续运行,成功!虽然成功,但停车一看,原来兜了一个圈子,又回到了出发的地方。一切还是交由MVC处理,IoC容器形同虚设,Controller的依赖注入无法实现。如果这时访问想依赖注入的Controller(构造函数带有参数),会出现下面的错误提示: No parameterless constructor defined for this object. 虽然回到原地,看上去没有前进一步,但实际上你已离目标更近一些(积累了经验,下次前进速度会更快)。就像你追一个女孩子,费尽心思,却被拒绝,看似你的一切努力付之流水,实际上她的心门已经有点松动。。。这时,你要有一种锲而不舍的精神,把失落感扔到九霄云外,然后继续努力,坚信“精诚所至,金石为开”。解决技术问题也是同样道理。重头再来!阅读MVC的源代码,了解MVC的请求处理过程,看看MVC是在什么地方创建Controller的实例的,然后看有没有办法让IoC容器来接管。MvcHandler.BeginProcessRequest->MvcHandler.ProcessRequestInit,呵呵,找到: factory = ControllerBuilder.GetControllerFactory(); controller = factory.CreateController(RequestContext, controllerName); 上面的代码中,factory的类型是IControllerFactory,ControllerBuilder.GetControllerFactory()的作用是获取IControllerFactory的实现实例,而实际是通过调用IDependencyResolver接口得到的(我们之前实现的UnityDependencyResolver接管了IDependencyResolver接口)。但我们没有在IoC容器中注册IControllerFactory,实际是由MVC返回IControllerFactory的默认实现DefaultControllerFactory。从上面的代码还可以看出,Controller实例的创建是通过调用IControllerFactory.CreateController()方法,所以,我们要在DefaultControllerFactory.CreateController()方法中寻找线索,对应代码如下: public virtual IController CreateController(RequestContext requestContext, string controllerName) { Type controllerType = GetControllerType(requestContext, controllerName); IController controller = GetControllerInstance(requestContext, controllerType); return controller; } CreateController()又调用了GetControllerInstance()得到Controller的实例,进一步查看其代码: protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return ControllerActivator.Create(requestContext, controllerType); } ControllerActivator的类型是IControllerActivator,之前也提到过,IControllerActivator的默认实现是DefaultControllerActivator,由此可以看出,Controller实例的创建是由DefaultControllerActivator完成的。我们要实现依赖注入,就要由IoC容器来接管。那如何来接管呢?——重载DefaultControllerFactory的CreateController方法,将创建Controller实例的工作转交给IoC容器,代码如下: public class UnityControllerFactory : DefaultControllerFactory { IUnityContainer container; public UnityControllerFactory(IUnityContainer container) { this.container = container; } protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType) { return container.Resolve(controllerType) as IController; } } 然后在IoC容器中注册一下UnityControllerFactory: container.RegisterType(); 然后,运行程序。。。功夫不负有心人,依赖注入成功,问题解决!从此,MVC与IoC过上了幸福的生活。[[40974]] 小结要实现ASP.NET MVC控制器的依赖注入,我们需要:1. 实现IDependencyResolver接口并通过DependencyResolver.SetResolver告知MVC,将部分类型实例解析工作交由IoC容器来处理;2. 继承DefaultControllerFactory,重载GetControllerInstance方法,并通过IoC容器将之注册为IControllerFactory的实现。完整示例代码下载原文:http://www.cnblogs.com/dudu/archive/2011/08/15/mvc_ioc_dependency_injection.html 网页标题:想爱容易相处难:当ASP.NETMVC爱上IoC 网站链接:http://www.csdahua.cn/qtweb/news12/294462.html 网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等 广告 声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网 成都快上网为您推荐相关内容 创新互联Python教程:python如何获取cookie mongodb查询索引 react如何返回html 服务器启动不起来是什么原因 妙啊,阻塞到底是个啥?黄袍加身,亦能谈古说今 Vue2移动端开发环境搭建 公司给了个ip地址怎么连接网络?(租用ip地址怎么联网的) 游戏行业租用服务器怎么提高访问速度 为什么手机浏览器会有 网站排名知识 网络号和主机号怎么算?(如何计算网络号和主机号) 全国活跃ip段是什么,全国活跃ip段的特征和应用 设置Redis集群设置用户名和密码(redis集群用户名密码) 每个Web开发者都应知道这10个优秀的GithubRepo 如何使用ODBParser搜索Elasticsearch和MongoDB目录数据 函数怎么做?(销售排名用RANK函数怎么做) 电脑挖矿怎么查看自己的显卡?(solo挖矿) Redis连接客户端的安全密码的重要性(redis连接客户端密码) 服务器平台 word里的表格范围什么意思 荣耀9短信设置在哪,请问短信设置中心在哪儿啊 搭建Linux系统无线网络连接(linux使用无线网卡) 香港服务器运营网站如何确保数据安全 创新互联Python教程:8.错误和异常 AI可以取代开发者么? 同城分类信息 混凝土搅拌罐 石雕 宣传片制作 搬家公司 混凝土泵车 玻璃钢坐凳 发电机维修 自上料搅拌车 混凝土搅拌罐车 墙体彩绘 轻质隔墙板 PVC花箱 食品包装袋 石牌坊 会所设计 服务器托管 成都做网站建设公司 宜宾做网站 资阳发电机 成都全屋定制 网站域名 成都展柜厂 贵阳托管服务器 雅安主机托管 网站运维托管 茶叶批发零售 成都营销型网站建设 兴久牧业 教育培训网站建设方案 达州网站建设 成都微信小程序 成都网站改版 中建建业环保 瑞杰管理 注册域名 成都公司注册
UnityDependencyResolver的作用就是调用IoC容器(这里是Unity)解析相应类型的实例。创建了UnityDependencyResolver,我们还需要告诉MVC用它进行解析。在Global.asax的Application_Start()方法中添加如下代码:
protected void Application_Start() { IUnityContainer container = new UnityContainer(); DependencyResolver.SetResolver(new UnityDependencyResolver(container)); }
我们运行一下程序试试,出现下面的错误提示:
The current type, System.Web.Mvc.IControllerFactory, is an interface and cannot be constructed. Are you missing a type mapping?
从上面的错误信息可以分析出,错误是发生在调用UnityDependencyResolver.GetService方法时。ASP.NET MVC在运行的时候需要得到IControllerFactory的实现实例,然后用它去创建相应的控制器实例。如果不用IoC容器,MVC默认会创建DefaultControllerFactory的实例。现在用了IoC,MVC找不到IControllerFactory的实现实例(我们根本没有注册嘛),所以出现上面的错误。
为了解决这个问题,我们注册一下DefaultControllerFactory:
container.RegisterType();
继续运行程序,又出现新的错误:
The current type, System.Web.Mvc.IControllerActivator, is an interface and cannot be constructed. Are you missing a type mapping?
找不到IControllerActivator的实现实例,看来,创建Controller还需要这个东东。查看MVC的源代码发现IControllerActivator的默认实现是DefaultControllerActivator,但郁闷的是它竟然是private class,无法注册它。别无选择,只能自己实现IControllerActivator,名叫CustomControllerActivator,代码如下:
public class CustomControllerActivator : IControllerActivator { IController IControllerActivator.Create( System.Web.Routing.RequestContext requestContext, Type controllerType) { return DependencyResolver.Current .GetService(controllerType) as IController; } }
继续运行,又出现新的错误:
The current type, System.Web.Mvc.IViewPageActivator, is an interface and cannot be constructed. Are you missing a type mapping?
天哪!难道MVC中的所有接口都要注册一下。。。
这时,脑子里突然闪出一个指示牌:
[[40973]]
于是,脚踩刹车,打了一把方向盘,驶上了另一条道 —— 如果IoC容器中没有注册,不引发异常,而是返回null,让MVC用自己的方式去处理。
修改UnityDependencyResolver的GetService方法:
public object GetService(Type serviceType) { if (!this.container.IsRegistered(serviceType)) { return null; } return container.Resolve(serviceType); }
并取消之前在IoC容器中对DefaultControllerFactory与CustomControllerActivator的注册。
继续运行,成功!虽然成功,但停车一看,原来兜了一个圈子,又回到了出发的地方。一切还是交由MVC处理,IoC容器形同虚设,Controller的依赖注入无法实现。如果这时访问想依赖注入的Controller(构造函数带有参数),会出现下面的错误提示:
No parameterless constructor defined for this object.
虽然回到原地,看上去没有前进一步,但实际上你已离目标更近一些(积累了经验,下次前进速度会更快)。就像你追一个女孩子,费尽心思,却被拒绝,看似你的一切努力付之流水,实际上她的心门已经有点松动。。。这时,你要有一种锲而不舍的精神,把失落感扔到九霄云外,然后继续努力,坚信“精诚所至,金石为开”。解决技术问题也是同样道理。
重头再来!阅读MVC的源代码,了解MVC的请求处理过程,看看MVC是在什么地方创建Controller的实例的,然后看有没有办法让IoC容器来接管。
MvcHandler.BeginProcessRequest->MvcHandler.ProcessRequestInit,呵呵,找到:
factory = ControllerBuilder.GetControllerFactory(); controller = factory.CreateController(RequestContext, controllerName);
上面的代码中,factory的类型是IControllerFactory,ControllerBuilder.GetControllerFactory()的作用是获取IControllerFactory的实现实例,而实际是通过调用IDependencyResolver接口得到的(我们之前实现的UnityDependencyResolver接管了IDependencyResolver接口)。但我们没有在IoC容器中注册IControllerFactory,实际是由MVC返回IControllerFactory的默认实现DefaultControllerFactory。从上面的代码还可以看出,Controller实例的创建是通过调用IControllerFactory.CreateController()方法,所以,我们要在DefaultControllerFactory.CreateController()方法中寻找线索,对应代码如下:
public virtual IController CreateController(RequestContext requestContext, string controllerName) { Type controllerType = GetControllerType(requestContext, controllerName); IController controller = GetControllerInstance(requestContext, controllerType); return controller; }
CreateController()又调用了GetControllerInstance()得到Controller的实例,进一步查看其代码:
protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return ControllerActivator.Create(requestContext, controllerType); }
ControllerActivator的类型是IControllerActivator,之前也提到过,IControllerActivator的默认实现是DefaultControllerActivator,由此可以看出,Controller实例的创建是由DefaultControllerActivator完成的。我们要实现依赖注入,就要由IoC容器来接管。
那如何来接管呢?——重载DefaultControllerFactory的CreateController方法,将创建Controller实例的工作转交给IoC容器,代码如下:
public class UnityControllerFactory : DefaultControllerFactory { IUnityContainer container; public UnityControllerFactory(IUnityContainer container) { this.container = container; } protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType) { return container.Resolve(controllerType) as IController; } }
然后在IoC容器中注册一下UnityControllerFactory:
然后,运行程序。。。功夫不负有心人,依赖注入成功,问题解决!从此,MVC与IoC过上了幸福的生活。
[[40974]]
小结
要实现ASP.NET MVC控制器的依赖注入,我们需要:
1. 实现IDependencyResolver接口并通过DependencyResolver.SetResolver告知MVC,将部分类型实例解析工作交由IoC容器来处理;
2. 继承DefaultControllerFactory,重载GetControllerInstance方法,并通过IoC容器将之注册为IControllerFactory的实现。
完整示例代码下载
原文:http://www.cnblogs.com/dudu/archive/2011/08/15/mvc_ioc_dependency_injection.html
网页标题:想爱容易相处难:当ASP.NETMVC爱上IoC 网站链接:http://www.csdahua.cn/qtweb/news12/294462.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
广告
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网
成都快上网为您推荐相关内容
网站排名知识
同城分类信息
在线客服
电话咨询
7*24小时客服热线
建站咨询
微信咨询