本篇文章為大家展示了使用Spring.Net怎么在MVC中實現(xiàn)注入,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
創(chuàng)新互聯(lián)于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目網(wǎng)站建設(shè)、成都做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元邊壩做網(wǎng)站,已為上家服務(wù),為邊壩各地企業(yè)和個人服務(wù),聯(lián)系電話:18980820575
情景
public class HomeController : Controller
{
//這是一個很神奇的注入
private IBLL.IUserInfoService UserInfoService { get; set; }
public ActionResult Index()
{
return Content(UserInfoService.GetName());
}
}每次看代碼都有不一樣的理解,今天我在看MVC控制器中一個通過Spring.Net依賴注入的UserInfoService屬性時,突然有些疑問,注入的前提是控制反轉(zhuǎn),這么說我的Controller是從IoC容器中來的了?但是我不記得在哪個地方有配置額,對此我展開了深入的研究。
從MVC本身開始
首先我們要搞懂MVC本身是通過什么方式獲取控制器對象的,本質(zhì)如果都沒有搞懂,又何來擴展呢?
在MVC模式下,通過實現(xiàn)IControllerFactory接口的對象來獲取當(dāng)前請求的控制器對象,實現(xiàn)IControllerFactory接口的對象也就是控制器的創(chuàng)建工廠。
簡單看下IControllerFactory
//
// 摘要:
// 定義控制器工廠所需的方法。
public interface IControllerFactory
{
//
// 摘要:
// 使用指定的請求上下文來創(chuàng)建指定的控制器。
//
// 參數(shù):
// requestContext:
// 請求上下文。
//
// controllerName:
// 控制器的名稱。
//
// 返回結(jié)果:
// 控制器。
IController CreateController(RequestContext requestContext, string controllerName);
//
// 摘要:
// 獲取控制器的會話行為。
//
// 參數(shù):
// requestContext:
// 請求上下文。
//
// controllerName:
// 你想要獲取器其會話行為的控制器的名稱。
//
// 返回結(jié)果:
// 控制器的會話行為。
SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
//
// 摘要:
// 釋放指定的控制器。
//
// 參數(shù):
// controller:
// 控制器。
void ReleaseController(IController controller);
}一個Http請求過來,選擇哪個控制器是通過MvcHandler來處理的
控制器工廠是通過ControllerBuilder的Current屬性提供給MvcHandler使用的
下面的代碼是反編譯過來的,簡單看下即可(因為我要標(biāo)記黃色高亮部分,所以沒有折疊)
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<MvcHandler.ProcessRequestState> <>9__20_0;
public static EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> <>9__20_1;
public static Func<KeyValuePair<string, object>, bool> <>9__26_0;
// Methods
static <>c();
public <>c();
internal IAsyncResult <BeginProcessRequest>b__20_0(AsyncCallback asyncCallback, object asyncState, MvcHandler.ProcessRequestState innerState);
internal void <BeginProcessRequest>b__20_1(IAsyncResult asyncResult, MvcHandler.ProcessRequestState innerState);
internal bool <RemoveOptionalRoutingParameters>b__26_0(KeyValuePair<string, object> entry);
}
[StructLayout(LayoutKind.Sequential)]
private struct ProcessRequestState
{
internal IAsyncController AsyncController;
internal IControllerFactory Factory;
internal RequestContext RequestContext;
internal void ReleaseController();
}
}默認工廠
默認情況下,在ControllerBuilder內(nèi)部會創(chuàng)建一個DefaultControllerFactory類型的對象,以提供處理請求。
DefaultControllerFactory是實現(xiàn)IControllerFactory接口的。
//
// 摘要:
// 表示默認情況下已注冊的控制器工廠。
public class DefaultControllerFactory : IControllerFactory
{
//
// 摘要:
// 初始化 System.Web.Mvc.DefaultControllerFactory 類的新實例。
public DefaultControllerFactory();
//
// 摘要:
// 使用控制器激活器來初始化 System.Web.Mvc.DefaultControllerFactory 類的新實例。
//
// 參數(shù):
// controllerActivator:
// 實現(xiàn)控制器激活器接口的對象。
public DefaultControllerFactory(IControllerActivator controllerActivator);
//
// 摘要:
// 使用指定的請求上下文來創(chuàng)建指定的控制器。
//
// 參數(shù):
// requestContext:
// HTTP 請求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。
//
// controllerName:
// 控制器的名稱。
//
// 返回結(jié)果:
// 控制器。
//
// 異常:
// T:System.ArgumentNullException:
// requestContext 參數(shù)為 null。
//
// T:System.ArgumentException:
// controllerName 參數(shù)為 null 或為空。
public virtual IController CreateController(RequestContext requestContext, string controllerName);
//
// 摘要:
// 釋放指定的控制器。
//
// 參數(shù):
// controller:
// 要釋放的控制器。
public virtual void ReleaseController(IController controller);
//
// 摘要:
// 檢索指定請求上下文和控制器類型的控制器實例。
//
// 參數(shù):
// requestContext:
// HTTP 請求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。
//
// controllerType:
// 控制器的類型。
//
// 返回結(jié)果:
// 控制器實例。
//
// 異常:
// T:System.Web.HttpException:
// controllerType 為 null。
//
// T:System.ArgumentException:
// 無法分配 controllerType。
//
// T:System.InvalidOperationException:
// 無法創(chuàng)建 controllerType 的實例。
protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType);
//
// 摘要:
// 返回控制器的會話行為。
//
// 參數(shù):
// requestContext:
// 請求上下文。
//
// controllerType:
// 控制器的類型。
//
// 返回結(jié)果:
// 控制器的會話行為。
protected internal virtual SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType);
//
// 摘要:
// 檢索指定名稱和請求上下文的控制器類型。
//
// 參數(shù):
// requestContext:
// HTTP 請求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。
//
// controllerName:
// 控制器的名稱。
//
// 返回結(jié)果:
// 控制器類型。
protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName);
}默認情況下,Controller類需要提供默認的構(gòu)造函數(shù),因為DefaultControllerFactory是通過反射來創(chuàng)建Controller對象實例的。
如果我們定義的Controller需要通過構(gòu)造函數(shù)創(chuàng)建,或者通過某個IoC容器管理Controller,可以通過自定義控制器工廠來實現(xiàn)。
自定義控制器工廠
為什么說這么多關(guān)于控制器工廠的東西呢,其實Spring.Net就是通過繼承DefaultControllerFactory創(chuàng)建SpringControllerFactory的。
說了這么多就是為了后面可以更容易的理解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只是一個很簡陋的測試類,只有一個GetName()方法用來返回“小明”。
接下來將通過自定義控制器工廠實現(xiàn)構(gòu)造注入UserInfoService
2.創(chuàng)建控制器工廠MyControllerFactory
為了方便我直接繼承了DefaultControllerFactory,當(dāng)然也可以通過實現(xiàn)IControllerFactory來創(chuàng)建
public class MyControllerFactory : DefaultControllerFactory
{
private static readonly IBLL.IUserInfoService userInfoService = new BLL.UserInfoService();
//重寫CreateController
public override IController CreateController(RequestContext requestContext, string controllerName)
{
IController controller = null;
if (controllerName == "Home")
{
//如果是我們制定的Home控制器則給其實例化,并通過構(gòu)造參數(shù)注入userInfoService
controller = new HomeController(userInfoService);
}
else
{
//通過默認控制器工廠創(chuàng)建控制器
controller = base.CreateController(requestContext, controllerName);
}
return controller;
}
}3.在Global.asax中注冊
protected void Application_Start()
{
MyControllerFactory myControllerFactory = new MyControllerFactory();
//通過ControllerBuilder設(shè)置制定的控制器工廠
ControllerBuilder.Current.SetControllerFactory(myControllerFactory);
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}4.運行測試(神奇不再神奇)

意料之外,情理之中,我們并沒有在控制器中實例化,結(jié)果卻出來了
(實例化在工廠中完成了)
Spring.Net注入原理
說了這么多,回頭看看標(biāo)題“Spring.Net是怎么在MVC中實現(xiàn)注入的”,你倒是說啊,等的花都謝了,連Spring.Net的毛都沒看到.....
其實,如果你是認真讀過來的,答案在你心中應(yīng)該已經(jīng)有了。
答案如下
namespace Spring.Web.Mvc
{
/// <summary>
/// Controller Factory for ASP.NET MVC
/// </summary>
public class SpringControllerFactory : DefaultControllerFactory
{
private static IApplicationContext _context;
/// <summary>
/// Gets the application context.
/// </summary>
/// <value>The application context.</value>
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;
}
}
/// <summary>
/// Gets or sets the name of the application context.
/// </summary>
/// <remarks>
/// Defaults to using the root (default) Application Context.
/// </remarks>
/// <value>The name of the application context.</value>
public static string ApplicationContextName { get; set; }
/// <summary>
/// Creates the specified controller by using the specified request context.
/// </summary>
/// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
/// <param name="controllerName">The name of the controller.</param>
/// <returns>A reference to the controller.</returns>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext"/> parameter is null.</exception>
/// <exception cref="T:System.ArgumentException">The <paramref name="controllerName"/> parameter is null or empty.</exception>
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;
}
/// <summary>
/// Retrieves the controller instance for the specified request context and controller type.
/// </summary>
/// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
/// <param name="controllerType">The type of the controller.</param>
/// <returns>The controller instance.</returns>
/// <exception cref="T:System.Web.HttpException">
/// <paramref name="controllerType"/> is null.</exception>
/// <exception cref="T:System.ArgumentException">
/// <paramref name="controllerType"/> cannot be assigned.</exception>
/// <exception cref="T:System.InvalidOperationException">An instance of <paramref name="controllerType"/> cannot be created.</exception>
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;
}
/// <summary>
/// Adds the action invoker to the controller instance.
/// </summary>
/// <param name="controller">The controller.</param>
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中實現(xiàn)注入,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
本文題目:使用Spring.Net怎么在MVC中實現(xiàn)注入
標(biāo)題路徑:http://chinadenli.net/article32/jiicpc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、品牌網(wǎng)站建設(shè)、定制網(wǎng)站、營銷型網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計、網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)