日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

想爱容易,相处难:当ASP.NET MVC爱上IoC

發布時間:2025/5/22 asp.net 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 想爱容易,相处难:当ASP.NET MVC爱上IoC 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  也許你會問ASP.NET MVC為什么會愛上IoC?

  相愛的理由常常很簡單,就像一首歌中所唱——“只為相遇那一個眼神”。

  而ASP.NET MVC愛上IoC只為IoC能實現MVC控制器的依賴注入。

  下面是博客園招聘頻道(job.cnblogs.com)所用的一個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<object> 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<IControllerFactory, DefaultControllerFactory>();

  繼續運行程序,又出現新的錯誤:

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中的所有接口都要注冊一下。。。

  這時,腦子里突然閃出一個指示牌:

  于是,腳踩剎車,打了一把方向盤,駛上了另一條道 —— 如果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<IControllerFactory, UnityControllerFactory>();

  然后,運行程序。。。功夫不負有心人,依賴注入成功,問題解決!從此,MVC與IoC過上了幸福的生活。

  小結

  要實現ASP.NET MVC控制器的依賴注入,我們需要:

  1. 實現IDependencyResolver接口并通過DependencyResolver.SetResolver告知MVC,將部分類型實例解析工作交由IoC容器來處理;

  2. 繼承DefaultControllerFactory,重載GetControllerInstance方法,并通過IoC容器將之注冊為IControllerFactory的實現。

  完整示例代碼下載

總結

以上是生活随笔為你收集整理的想爱容易,相处难:当ASP.NET MVC爱上IoC的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。