本篇文章為大家展示了使用Spring.Net怎么在MVC中實(shí)現(xiàn)注入,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。
創(chuàng)新互聯(lián)于2013年成立,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站建設(shè)、成都做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元邊壩做網(wǎng)站,已為上家服務(wù),為邊壩各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575
情景
public class HomeController : Controller { //這是一個(gè)很神奇的注入 private IBLL.IUserInfoService UserInfoService { get; set; } public ActionResult Index() { return Content(UserInfoService.GetName()); } }
每次看代碼都有不一樣的理解,今天我在看MVC控制器中一個(gè)通過(guò)Spring.Net依賴(lài)注入的UserInfoService屬性時(shí),突然有些疑問(wèn),注入的前提是控制反轉(zhuǎn),這么說(shuō)我的Controller是從IoC容器中來(lái)的了?但是我不記得在哪個(gè)地方有配置額,對(duì)此我展開(kāi)了深入的研究。
從MVC本身開(kāi)始
首先我們要搞懂MVC本身是通過(guò)什么方式獲取控制器對(duì)象的,本質(zhì)如果都沒(méi)有搞懂,又何來(lái)擴(kuò)展呢?
在MVC模式下,通過(guò)實(shí)現(xiàn)IControllerFactory接口的對(duì)象來(lái)獲取當(dāng)前請(qǐng)求的控制器對(duì)象,實(shí)現(xiàn)IControllerFactory接口的對(duì)象也就是控制器的創(chuàng)建工廠。
簡(jiǎn)單看下IControllerFactory
// // 摘要: // 定義控制器工廠所需的方法。 public interface IControllerFactory { // // 摘要: // 使用指定的請(qǐng)求上下文來(lái)創(chuàng)建指定的控制器。 // // 參數(shù): // requestContext: // 請(qǐng)求上下文。 // // controllerName: // 控制器的名稱(chēng)。 // // 返回結(jié)果: // 控制器。 IController CreateController(RequestContext requestContext, string controllerName); // // 摘要: // 獲取控制器的會(huì)話行為。 // // 參數(shù): // requestContext: // 請(qǐng)求上下文。 // // controllerName: // 你想要獲取器其會(huì)話行為的控制器的名稱(chēng)。 // // 返回結(jié)果: // 控制器的會(huì)話行為。 SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName); // // 摘要: // 釋放指定的控制器。 // // 參數(shù): // controller: // 控制器。 void ReleaseController(IController controller); }
一個(gè)Http請(qǐng)求過(guò)來(lái),選擇哪個(gè)控制器是通過(guò)MvcHandler來(lái)處理的
控制器工廠是通過(guò)ControllerBuilder的Current屬性提供給MvcHandler使用的
下面的代碼是反編譯過(guò)來(lái)的,簡(jiǎn)單看下即可(因?yàn)槲乙獦?biāo)記黃色高亮部分,所以沒(méi)有折疊)
internal ControllerBuilder ControllerBuilder { get { if (this._controllerBuilder == null) { this._controllerBuilder = ControllerBuilder.Current; } return this._controllerBuilder; } set { this._controllerBuilder = value; } }
public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState { // Fields private ControllerBuilder _controllerBuilder; private static readonly object _processRequestTag; internal static readonly string MvcVersion; public static readonly string MvcVersionHeaderName; // Methods static MvcHandler(); public MvcHandler(RequestContext requestContext); protected internal virtual void AddVersionHeader(HttpContextBase httpContext); protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state); protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state); protected internal virtual void EndProcessRequest(IAsyncResult asyncResult); private static string GetMvcVersionString(); protected virtual void ProcessRequest(HttpContext httpContext); protected internal virtual void ProcessRequest(HttpContextBase httpContext); private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory); private void RemoveOptionalRoutingParameters(); IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData); void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result); void IHttpHandler.ProcessRequest(HttpContext httpContext); // Properties internal ControllerBuilder ControllerBuilder { get; set; } public static bool DisableMvcResponseHeader { get; [CompilerGenerated] set; } protected virtual bool IsReusable { get; } public RequestContext RequestContext { get; [CompilerGenerated] private set; } bool IHttpHandler.IsReusable { get; } // Nested Types [Serializable, CompilerGenerated] private sealed class <>c { // Fields public static readonly MvcHandler.<>c <>9; public static BeginInvokeDelegate<>9__20_0; public static EndInvokeVoidDelegate <>9__20_1; public static Func , bool> <>9__26_0; // Methods static <>c(); public <>c(); internal IAsyncResult b__20_0(AsyncCallback asyncCallback, object asyncState, MvcHandler.ProcessRequestState innerState); internal void b__20_1(IAsyncResult asyncResult, MvcHandler.ProcessRequestState innerState); internal bool b__26_0(KeyValuePair entry); } [StructLayout(LayoutKind.Sequential)] private struct ProcessRequestState { internal IAsyncController AsyncController; internal IControllerFactory Factory; internal RequestContext RequestContext; internal void ReleaseController(); } }
默認(rèn)工廠
默認(rèn)情況下,在ControllerBuilder內(nèi)部會(huì)創(chuàng)建一個(gè)DefaultControllerFactory類(lèi)型的對(duì)象,以提供處理請(qǐng)求。
DefaultControllerFactory是實(shí)現(xiàn)IControllerFactory接口的。
// // 摘要: // 表示默認(rèn)情況下已注冊(cè)的控制器工廠。 public class DefaultControllerFactory : IControllerFactory { // // 摘要: // 初始化 System.Web.Mvc.DefaultControllerFactory 類(lèi)的新實(shí)例。 public DefaultControllerFactory(); // // 摘要: // 使用控制器激活器來(lái)初始化 System.Web.Mvc.DefaultControllerFactory 類(lèi)的新實(shí)例。 // // 參數(shù): // controllerActivator: // 實(shí)現(xiàn)控制器激活器接口的對(duì)象。 public DefaultControllerFactory(IControllerActivator controllerActivator); // // 摘要: // 使用指定的請(qǐng)求上下文來(lái)創(chuàng)建指定的控制器。 // // 參數(shù): // requestContext: // HTTP 請(qǐng)求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。 // // controllerName: // 控制器的名稱(chēng)。 // // 返回結(jié)果: // 控制器。 // // 異常: // T:System.ArgumentNullException: // requestContext 參數(shù)為 null。 // // T:System.ArgumentException: // controllerName 參數(shù)為 null 或?yàn)榭铡? public virtual IController CreateController(RequestContext requestContext, string controllerName); // // 摘要: // 釋放指定的控制器。 // // 參數(shù): // controller: // 要釋放的控制器。 public virtual void ReleaseController(IController controller); // // 摘要: // 檢索指定請(qǐng)求上下文和控制器類(lèi)型的控制器實(shí)例。 // // 參數(shù): // requestContext: // HTTP 請(qǐng)求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。 // // controllerType: // 控制器的類(lèi)型。 // // 返回結(jié)果: // 控制器實(shí)例。 // // 異常: // T:System.Web.HttpException: // controllerType 為 null。 // // T:System.ArgumentException: // 無(wú)法分配 controllerType。 // // T:System.InvalidOperationException: // 無(wú)法創(chuàng)建 controllerType 的實(shí)例。 protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType); // // 摘要: // 返回控制器的會(huì)話行為。 // // 參數(shù): // requestContext: // 請(qǐng)求上下文。 // // controllerType: // 控制器的類(lèi)型。 // // 返回結(jié)果: // 控制器的會(huì)話行為。 protected internal virtual SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType); // // 摘要: // 檢索指定名稱(chēng)和請(qǐng)求上下文的控制器類(lèi)型。 // // 參數(shù): // requestContext: // HTTP 請(qǐng)求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。 // // controllerName: // 控制器的名稱(chēng)。 // // 返回結(jié)果: // 控制器類(lèi)型。 protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName); }
默認(rèn)情況下,Controller類(lèi)需要提供默認(rèn)的構(gòu)造函數(shù),因?yàn)镈efaultControllerFactory是通過(guò)反射來(lái)創(chuàng)建Controller對(duì)象實(shí)例的。
如果我們定義的Controller需要通過(guò)構(gòu)造函數(shù)創(chuàng)建,或者通過(guò)某個(gè)IoC容器管理Controller,可以通過(guò)自定義控制器工廠來(lái)實(shí)現(xiàn)。
自定義控制器工廠
為什么說(shuō)這么多關(guān)于控制器工廠的東西呢,其實(shí)Spring.Net就是通過(guò)繼承DefaultControllerFactory創(chuàng)建SpringControllerFactory的。
說(shuō)了這么多就是為了后面可以更容易的理解Spring.Net的控制器工廠源碼罷了。
回歸正題,接著創(chuàng)建自己的控制器工廠。
1.Home控制器內(nèi)容如下
public class HomeController : Controller { private IUserInfoService UserInfoService { get; set; } public HomeController(IUserInfoService userInfoService) { UserInfoService = userInfoService; } public ActionResult Index() { return Content(UserInfoService.GetName()); } }
這里的UserInfoService只是一個(gè)很簡(jiǎn)陋的測(cè)試類(lèi),只有一個(gè)GetName()方法用來(lái)返回“小明”。
接下來(lái)將通過(guò)自定義控制器工廠實(shí)現(xiàn)構(gòu)造注入U(xiǎn)serInfoService
2.創(chuàng)建控制器工廠MyControllerFactory
為了方便我直接繼承了DefaultControllerFactory,當(dāng)然也可以通過(guò)實(shí)現(xiàn)IControllerFactory來(lái)創(chuàng)建
public class MyControllerFactory : DefaultControllerFactory { private static readonly IBLL.IUserInfoService userInfoService = new BLL.UserInfoService(); //重寫(xiě)CreateController public override IController CreateController(RequestContext requestContext, string controllerName) { IController controller = null; if (controllerName == "Home") { //如果是我們制定的Home控制器則給其實(shí)例化,并通過(guò)構(gòu)造參數(shù)注入userInfoService controller = new HomeController(userInfoService); } else { //通過(guò)默認(rèn)控制器工廠創(chuàng)建控制器 controller = base.CreateController(requestContext, controllerName); } return controller; } }
3.在Global.asax中注冊(cè)
protected void Application_Start() { MyControllerFactory myControllerFactory = new MyControllerFactory(); //通過(guò)ControllerBuilder設(shè)置制定的控制器工廠 ControllerBuilder.Current.SetControllerFactory(myControllerFactory); AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); }
4.運(yùn)行測(cè)試(神奇不再神奇)
意料之外,情理之中,我們并沒(méi)有在控制器中實(shí)例化,結(jié)果卻出來(lái)了
(實(shí)例化在工廠中完成了)
Spring.Net注入原理
說(shuō)了這么多,回頭看看標(biāo)題“Spring.Net是怎么在MVC中實(shí)現(xiàn)注入的”,你倒是說(shuō)啊,等的花都謝了,連Spring.Net的毛都沒(méi)看到.....
其實(shí),如果你是認(rèn)真讀過(guò)來(lái)的,答案在你心中應(yīng)該已經(jīng)有了。
答案如下
namespace Spring.Web.Mvc { ////// Controller Factory for ASP.NET MVC /// public class SpringControllerFactory : DefaultControllerFactory { private static IApplicationContext _context; ////// Gets the application context. /// ///The application context. public static IApplicationContext ApplicationContext { get { if (_context == null || _context.Name != ApplicationContextName) { if (string.IsNullOrEmpty(ApplicationContextName)) { _context = ContextRegistry.GetContext(); } else { _context = ContextRegistry.GetContext(ApplicationContextName); } } return _context; } } ////// Gets or sets the name of the application context. /// ////// Defaults to using the root (default) Application Context. /// ///The name of the application context. public static string ApplicationContextName { get; set; } ////// Creates the specified controller by using the specified request context. /// /// The context of the HTTP request, which includes the HTTP context and route data. /// The name of the controller. ///A reference to the controller. ///The ///parameter is null. The public override IController CreateController(RequestContext requestContext, string controllerName) { IController controller; if (ApplicationContext.ContainsObjectDefinition(controllerName)) { controller = ApplicationContext.GetObject(controllerName) as IController; } else { controller = base.CreateController(requestContext, controllerName); } AddActionInvokerTo(controller); return controller; } ///parameter is null or empty. /// Retrieves the controller instance for the specified request context and controller type. /// /// The context of the HTTP request, which includes the HTTP context and route data. /// The type of the controller. ///The controller instance. ////// ///is null. /// ///cannot be assigned. An instance of protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { IController controller = null; if (controllerType != null) { var controllers = ApplicationContext.GetObjectsOfType(controllerType); if (controllers.Count > 0) { controller = (IController)controllers.First().Value; } } if (controller == null) { //pass to base class for remainder of handling if can't find it in the context controller = base.GetControllerInstance(requestContext, controllerType); } AddActionInvokerTo(controller); return controller; } ///cannot be created. /// Adds the action invoker to the controller instance. /// /// The controller. protected virtual void AddActionInvokerTo(IController controller) { if (controller == null) return; if (typeof(Controller).IsAssignableFrom(controller.GetType())) { ((Controller)controller).ActionInvoker = new SpringActionInvoker(ApplicationContext); } } } }
上述內(nèi)容就是使用Spring.Net怎么在MVC中實(shí)現(xiàn)注入,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。