前言:上篇介紹了下 MVC5 的核心原理,整篇文章比較偏理論,因此相對比較枯燥。今天就來根據上篇的理論一步一步進行實踐,經過本身寫的一個簡易MVC框架逐步理解,相信經過這一篇的實踐,你會對MVC有一個更加清晰的認識。css
本文原創地址:http://www.cnblogs.com/landeanfen/p/6000978.htmlhtml
MVC源碼學習系列文章目錄:jquery
這篇博主打算從零開始一步一步來加上MVC裏面用到的一些技術,整篇經過三個版本,逐步完善。git
經過上篇的介紹,咱們知道,MVC裏面兩個最核心的部件:MvcHandler和UrlRoutingModule。如今咱們就來一步一步實現它們。爲了更加真實,咱們徹底從零開始。github
咱們新建兩個文件,而後實現IHttpHandler和IHttpModule。咱們知道這兩個接口都在System.Web裏面,首先咱們在類庫項目裏面引用Syste.Web這個dll,而後來看具體的代碼。web
MvcHandler.cs代碼:bootstrap
namespace Swift.MVC { public class MvcHandler : IHttpHandler { public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { context.Response.Write("當前頁面地址:" + context.Request.Url.AbsoluteUri + " "); context.Response.Write("Hello MVC"); } } }
UrlRoutingModule.cs代碼:swift
namespace Swift.MVC { public class UrlRoutingModule : IHttpModule { public void Dispose() { //throw new NotImplementedException(); } public void Init(HttpApplication app) { app.PostResolveRequestCache += app_PostResolveRequestCache; } void app_PostResolveRequestCache(object sender, EventArgs e) { var app = (HttpApplication)sender; app.Context.RemapHandler(new MvcHandler()); } } }
若是你看過博主的上篇,這個應該很好理解。UrlRoutingModule註冊PostResolveRequestCache事件,經過這個事件攔截當前的請求,攔截到請求以後,再交由MvcHandler去處理當前的http請求。整個過程就是這麼簡單,咱們最最基礎的「框架」就搭好了。app
第一步,新建一個空的Web項目,添加對Swift.MVC的引用,或者直接將Swift.MVC.dll拷貝到web項目的bin目錄下面,兩種方式都行,這裏爲了方便測試,咱們直接添加解決方案中的項目引用。框架
第二步,配置Web項目的web.config文件。上篇咱們就介紹過,HttpHandler和HttpModule的實現類要生效,就必需要在Web.config裏面註冊。註冊以後整個Web.config的內容以下:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" /> </system.web> <system.webServer> <handlers> <add name="swifthandler" verb="*" path="*" type="Swift.MVC.MvcHandler, Swift.MVC" preCondition="integratedMode" /> </handlers> <modules> <add name="swiftmodule" type="Swift.MVC.UrlRoutingModule, Swift.MVC" preCondition="integratedMode" /> </modules> </system.webServer> </configuration>
獲得結果
這裏博主想要說明兩點:
這裏經過以上實現和配置,咱們的Swift.MVC已經具備處理http請求的能力,但還不能算一個完整意義上的框架,下面來繼續完善。
這個版本,UrlRoutingModule咱們仍是沿用的System.Web.Routing裏面的機制,咱們主要來看看MvcHandler這部分的實現。
UrlRoutingModule.cs的完整代碼以下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Routing; namespace Swift.MVC { public class UrlRoutingModule : IHttpModule { #region Property private RouteCollection _routeCollection; [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "This needs to be settable for unit tests.")] public RouteCollection RouteCollection { get { if (_routeCollection == null) { _routeCollection = RouteTable.Routes; } return _routeCollection; } set { _routeCollection = value; } } #endregion public void Dispose() { //throw new NotImplementedException(); } public void Init(HttpApplication app) { app.PostResolveRequestCache += app_PostResolveRequestCache; } void app_PostResolveRequestCache(object sender, EventArgs e) { var app = (HttpApplication)sender; //0.將HttpContext轉換爲HttpContextWrapper對象(HttpContextWrapper繼承HttpContextBase) var contextbase = new HttpContextWrapper(app.Context); PostResolveRequestCache(contextbase); } public virtual void PostResolveRequestCache(HttpContextBase context) { //1.傳入當前上下文對象,獲得與當前請求匹配的RouteData對象 RouteData routeData = this.RouteCollection.GetRouteData(context); if (routeData == null) { return; } //2.從RouteData對象裏面獲得當前的RouteHandler對象。 IRouteHandler routeHandler = routeData.RouteHandler; if (routeHandler == null) { return; } //3.根據HttpContext和RouteData獲得RequestContext對象 RequestContext requestContext = new RequestContext(context, routeData); context.Request.RequestContext = requestContext; //4.根據RequestContext對象獲得處理當前請求的HttpHandler(MvcHandler)。 IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); if (httpHandler == null) { return; } //5.請求轉到HttpHandler進行處理(進入到ProcessRequest方法)。這一步很重要,由這一步開始,請求才由UrlRoutingModule轉到了MvcHandler裏面 context.RemapHandler(httpHandler); } } }
上述代碼基本都是從Framework源碼裏面拷貝出來的,註釋中的0、一、二、三、四、5分別對應着MVC路由過程當中的各個步驟,詳見上篇。
這裏咱們自定義了一個實現IRouteHandler的類型,用來返回處理請求的HttpHandler是哪一個,好比這裏咱們定義的MvcRouteHandler返回的HttpHandler是MvcHandler。它的代碼以下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.Routing; namespace Swift.MVC { public class MvcRouteHandler:IRouteHandler { public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext) { return new MvcHandler(); } } }
首先仍是拋出MvcHandler.cs的源碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; namespace Swift.MVC { public class MvcHandler : IHttpHandler { public virtual bool IsReusable { get { return false; } } public virtual void ProcessRequest(HttpContext context) { //寫入MVC的版本到HttpHeader裏面 //AddVersionHeader(httpContext); //移除參數 //RemoveOptionalRoutingParameters(); //步驟1.從上下文的Request.RequestContext中取到RouteData對象。這裏和UrlRoutingModule裏面的context.Request.RequestContext = requestContext;對應。 var routeData = context.Request.RequestContext.RouteData; //步驟2.從當前的RouteData裏面獲得請求的控制器名稱 string controllerName = routeData.GetRequiredString("controller"); //步驟3.獲得控制器工廠 IControllerFactory factory = new SwiftControllerFactory(); //步驟4.經過默認控制器工廠獲得當前請求的控制器對象 IController controller = factory.CreateController(context.Request.RequestContext, controllerName); if (controller == null) { return; } try { //步驟5.執行控制器的Action controller.Execute(context.Request.RequestContext); } catch { } finally { //步驟6.釋放當前的控制器對象 factory.ReleaseController(controller); } } } }
關於上述代碼,咱們說明如下幾點。
上述代碼註釋中的步驟一、2不難理解,就是從配置的路由規則中獲取當前請求控制器的名稱。要理解步驟3,須要先說一說MVC源碼裏面的控制器工廠。先來看看源碼裏面這段如何實現:
在源碼裏面的MvcHandler的ProcessRequest方法裏面有這麼一句: factory = ControllerBuilder.GetControllerFactory(); 。在MvcHandler裏面ControllerBuilder這樣定義:
internal ControllerBuilder ControllerBuilder { get { if (_controllerBuilder == null) { _controllerBuilder = ControllerBuilder.Current; } return _controllerBuilder; } set { _controllerBuilder = value; } }
原來在MvcHandler中建立控制器工廠並非直接使用IControllerFactroy的實現,而是使用了ControllerBuilder這個對象,這個對象採用了單例模式的實現;MvcHandler經過ControllerBuilder對象獲取到一個實例,而後經過ControllerBuilder建立出IControllerFactory實現,ControllerBuilder管理着IControllerFactory的建立過程。
關於ControllerBuilder裏面的GetControllerFactory()方法的實現,咱們沒必要細究,可是咱們須要知道的是在MVC裏面有一個默認的控制器工廠的實現類DefaultControllerFactory。咱們來看看
IControllerFactory接口的定義:
public interface IControllerFactory { IController CreateController(RequestContext requestContext, string controllerName); SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName); void ReleaseController(IController controller); }
DefaultControllerFactory的定義:
public class DefaultControllerFactory : IControllerFactory { public virtual IController CreateController(RequestContext requestContext, string controllerName) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } if (String.IsNullOrEmpty(controllerName) && !requestContext.RouteData.HasDirectRouteMatch()) { throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName"); } Type controllerType = GetControllerType(requestContext, controllerName); IController controller = GetControllerInstance(requestContext, controllerType); return controller; } public virtual void ReleaseController(IController controller) { IDisposable disposable = controller as IDisposable; if (disposable != null) { disposable.Dispose(); } } //...... }
上述的兩個方法CreateController()和ReleaseController()經過名字均可以很好理解,分別對應着建立控制器和釋放控制器。
瞭解了上述MVC裏面控制器工廠的實現細節,咱們本身也來建一個本身的控制器工廠,不過爲了簡化,咱們這裏直接去new了一個工廠的實現類。先來看看咱們Swift.MVC的控制器工廠。
控制器工廠接口:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.Routing; namespace Swift.MVC { //控制器建立工廠 public interface IControllerFactory { //建立控制器 IController CreateController(RequestContext requestContext, string controllerName); //釋放控制器 void ReleaseController(IController controller); } }
控制器工廠實現類:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Swift.MVC { public class SwiftControllerFactory:IControllerFactory { #region Public //經過當前的請求上下文和控制器名稱獲得控制器的對象 public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } if (string.IsNullOrEmpty(controllerName)) { throw new ArgumentException("controllerName"); } //獲得當前的控制類型 Type controllerType = GetControllerType(requestContext, controllerName); if (controllerType == null) { return null; } //獲得控制器對象 IController controller = GetControllerInstance(requestContext, controllerType); return controller; } //釋放控制器對象 public void ReleaseController(IController controller) { IDisposable disposable = controller as IDisposable; if (disposable != null) { disposable.Dispose(); } } #endregion #region Privates //獲得當前請求的控制器實例 private IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { var oRes = Activator.CreateInstance(controllerType) as IController; return oRes; } //獲得當前請求的控制器類型 private Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName) { //從路由配置信息裏面讀取命名空間和程序集 object routeNamespaces; object routeAssembly; requestContext.RouteData.Values.TryGetValue("namespaces", out routeNamespaces); requestContext.RouteData.Values.TryGetValue("assembly", out routeAssembly); //經過反射獲得控制器的類型 var type = Assembly.Load(routeAssembly.ToString()).GetType(routeNamespaces.ToString() + "." + controllerName + "Controller"); return type; } #endregion } }
這裏博主主要用到了反射去實例化控制器實例。
上述介紹了控制器工廠的實現。除了控制器工廠,還有咱們的控制器接口以及父類的相關實現。
控制器接口的定義:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.Routing; namespace Swift.MVC { public interface IController { void Execute(RequestContext requestContext); } }
控制器抽象Base類的實現:(這個抽象類的做用更多在於定義一些約束、檢查之類)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Swift.MVC { //這個類主要定義約束 public abstract class ControllerBase:IController { public abstract void Execute(System.Web.Routing.RequestContext requestContext); } }
控制器抽象子類的實現:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Swift.MVC { public abstract class Controller:ControllerBase,IDisposable { public override void Execute(System.Web.Routing.RequestContext requestContext) { //反射獲得Action方法 Type type = this.GetType(); string actionName = requestContext.RouteData.GetRequiredString("action"); System.Reflection.MethodInfo mi = type.GetMethod(actionName); //執行該Action方法 mi.Invoke(this, new object[] { });//調用方法 } public void Dispose() { //throw new NotImplementedException(); } } }
這裏讓Controller類實現IDispose接口,照應了上文控制器工廠裏面的ReleaseController()方法,主要起到釋放資源的做用。
因爲上述代碼用到了System.Web.Routing裏面的組件,因此,須要在測試項目裏面配置路由規則,這裏須要注意一點,咱們上面的MvcRouteHandler就是在這裏注入進去的。在測試項目裏面新建一個全局配置文件以下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Routing; using System.Web.Security; using System.Web.SessionState; namespace MyTestMVC { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.Add("defaultRoute", new Route("{controller}/{action}/{id}", new RouteValueDictionary(new { controller = "Home", action = "Index", id = "", namespaces = "MyTestMVC.Controllers", assembly = "MyTestMVC" }), new Swift.MVC.MvcRouteHandler())); } protected void Application_BeginRequest(object sender, EventArgs e) { } } }
而後在測試項目裏面模擬MVC新建一個Controllers文件夾,裏面新建一個測試的控制器HomeController:
using Swift.MVC; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MyTestMVC.Controllers { public class HomeController : Controller { public void Index() { HttpContext.Current.Response.Write("Hello MVC"); } } }
而後啓動項目,訪問http://localhost:16792/Home/Index。運行過程以及代碼釋疑以下:
(1)來看看 RouteData routeData = this.RouteCollection.GetRouteData(context); 這一句
經過上圖可知,this.RouteCollection裏面保存的是上述全局配置文件裏面添加進去的路由規則,而後調用GetRouteData(context)方法,傳入當前請求的上下文,獲得當前請求的RouteData對象,咱們能夠看到在這個RouteData對象裏面,已經包含了當前請求的控制器和action的名稱。
(2)監視 IRouteHandler routeHandler = routeData.RouteHandler;
經過上圖能夠看到在routeData裏面咱們的RouteHandler已是MvcRouteHandler對象了,還記得咱們在全局配置文件裏面有這樣一個配置:
RouteTable.Routes.Add("defaultRoute", new Route("{controller}/{action}/{id}", new RouteValueDictionary(new { controller = "Home", action = "Index", id = "", namespaces = "MyTestMVC.Controllers", assembly = "MyTestMVC" }), new Swift.MVC.MvcRouteHandler()));
在Add方法的最後須要傳一個IRouteHandler的對象,咱們上文定義過一個MvcRouteHandler去實現了IRouteHandler,這個MvcRouteHandler在這裏就派上用場了,原來咱們的RouteHandler是能夠自定義的。就是由於這裏配置過這個,因此在GetRouteData()方法裏面,就將MvcRouteHandler對象給了routeData對象的RouteHandler屬性,終於知道這裏的MvcRouteHandler是如何過來的了。這裏可配置IRouteHandler也說明了MVC原理的靈活性,咱們能夠自定義RouteHandler,而後再IRouteHandler接口的GetHttpHandler()方法裏面自定義處理當前請求的HttpHandler。
(3) RequestContext requestContext = new RequestContext(context, routeData);context.Request.RequestContext = requestContext; 這兩句看上去不起眼,就是封裝了一個RequestContext對象,而後將它給到了當前上下文的Request.RequestContext。實際上,這裏很是重要,由於這個requestContext對象包含了咱們當前請求的路由信息,後面MvcHandler裏面須要從這裏取到當前請求的控制器和Action的名稱,待會看了後面的代碼,你會更加清晰。
(4)再來看 IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); 這一句
上文註釋(2) 裏面說了,routeHandler對象其實是一個MvcRouteHandler對象,當它調用GetHttpHandler(),看下定義便可明白:
public class MvcRouteHandler:IRouteHandler { public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext) { return new MvcHandler(); } }
這裏就是返回了一個MvcHandler,用來處理Http請求。
(5) context.RemapHandler(httpHandler); 這一句天然沒必要多說,請當前攔截到的請求交給MvcHandler的ProcessRequest方法處理,這一句執行完成以後,請求便轉入到MvcHandler的ProcessRequest方法裏面。縱觀上述幾個過程,能夠說是一環扣一環,每一句都有它的意義所在,最後封裝完成以後,真正處理請求仍是在MvcHandler裏面。接下來咱們來看看ProcessRequest裏面的代碼。
(6)下面咱們來看看MvcHandler類裏面ProcessRequest方法這一句: var routeData = context.Request.RequestContext.RouteData; 。還記得上述註釋3中封裝的RequestContext對象嗎,沒錯,這裏就用到了這個對象,咱們從這個對象裏面取到當前請求的RouteData對象。
(7) string controllerName = routeData.GetRequiredString("controller"); 這一句不難理解:取到當前請求的的Controller名稱。結果以下:
(8)獲得控制器工廠這個沒什麼說的,爲了簡化,咱們直接new了一個默認的控制器工廠。下面重點來看看 IController controller = factory.CreateController(context.Request.RequestContext, controllerName); 這一句。在控制器工廠的實現類裏面實現了CreateController()這個方法。
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } if (string.IsNullOrEmpty(controllerName)) { throw new ArgumentException("controllerName"); } //獲得當前的控制類型 Type controllerType = GetControllerType(requestContext, controllerName); if (controllerType == null) { return null; } //獲得控制器對象 IController controller = GetControllerInstance(requestContext, controllerType); return controller; } //獲得當前請求的控制器實例 private IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { var oRes = Activator.CreateInstance(controllerType) as IController; return oRes; } //獲得當前請求的控制器類型 private Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName) { //從路由配置信息裏面讀取命名空間和程序集 object routeNamespaces; object routeAssembly; requestContext.RouteData.Values.TryGetValue("namespaces", out routeNamespaces); requestContext.RouteData.Values.TryGetValue("assembly", out routeAssembly); //經過反射獲得控制器的類型 var type = Assembly.Load(routeAssembly.ToString()).GetType(routeNamespaces.ToString() + "." + controllerName + "Controller"); return type; }
原理不難理解,主要仍是反射,由於咱們當前請求的控制器類在測試項目裏面,因此反射的時候須要指定當前測試項目的程序集,經過這裏的代碼能夠看出,在UrlRoutingModule裏面封裝的RequestContext對象實在是過重要了,由於各個地方都須要用到它。博主以爲這裏還有待優化,等想到更好的辦法再來逐步優化。此步獲得結果:
(9)獲得控制器對象以後,就是執行Action方法了: controller.Execute(context.Request.RequestContext); 。這裏博主按照源碼裏面的構造封裝了IController、ControllerBase、Controller三個級別的接口以及父類。Execute方法的實如今Controller裏面:
public abstract class Controller:ControllerBase,IDisposable { public override void Execute(System.Web.Routing.RequestContext requestContext) { //反射獲得Action方法 Type type = this.GetType(); string actionName = requestContext.RouteData.GetRequiredString("action"); System.Reflection.MethodInfo mi = type.GetMethod(actionName); //執行該Action方法 mi.Invoke(this, new object[] { });//調用方法 } }
這裏再次用到了RequestContext對象,由此能夠看出,RequestContext對象幾乎貫穿整個MvcHandler,再次應徵了上述註釋(3)中說的它的重要性。
上述代碼就是經過反射Action方法,而後執行該方法,以後請求就會盡到咱們HomeController的Index()方法裏面。
(10)執行Index()方法
請求進入到Index()方法以後,而後就是從Model裏面獲取數據,再而後就是返回View,整個MVC的原理就是如此。固然博主這裏的Swift.MVC還只是將請求轉到了Index裏面,剩餘的Model能夠本身寫,可是View的部分還徹底沒有,待有時間完善。
(11)執行完Action以後,最後就是釋放當前的Controller對象了。在finally裏面有這麼一句: factory.ReleaseController(controller); 。仍是來看看ReleaseController方法的定義:
//釋放控制器對象 public void ReleaseController(IController controller) { IDisposable disposable = controller as IDisposable; if (disposable != null) { disposable.Dispose(); } }
至此,咱們經過地址http://localhost:16792/Home/Index訪問,整個請求的開始、執行、資源釋放就基本結束。如今回過頭來理解這個原理,你以爲還難嗎~~
若是你還嫌上述例子太簡單,咱們能夠來個稍微複雜點的例子。咱們向測試項目裏面引入jquery、bootstrap等組件,添加Models文件夾,向下面加入User.cs
namespace MyTestMVC.Models { public class User { public int Id { get; set; } public string UserName { get; set; } public int Age { get; set; } public string Address { get; set; } public string Remark { get; set; } } }
而後咱們向HomeController裏面另外一個Action定義以下:
public void BootstrapTest() { var lstUser = new List<User>(); lstUser.Add(new User() { Id = 1, UserName = "Admin", Age = 20, Address = "北京", Remark = "超級管理員" }); lstUser.Add(new User() { Id = 2, UserName = "張三", Age = 37, Address = "湖南", Remark = "呵呵" }); lstUser.Add(new User() { Id = 3, UserName = "王五", Age = 32, Address = "廣西", Remark = "呵呵" }); lstUser.Add(new User() { Id = 4, UserName = "韓梅梅", Age = 26, Address = "上海", Remark = "呵呵" }); lstUser.Add(new User() { Id = 5, UserName = "呵呵", Age = 18, Address = "廣東", Remark = "呵呵" }); string strUser = string.Empty; foreach (var oUser in lstUser) { strUser += "<tr><td>" + oUser.Id + "</td><td>" + oUser.UserName + "</td><td>" + oUser.Age + "</td><td>" + oUser.Address + "</td><td>" + oUser.Remark + "</td></tr>"; } HttpContext.Current.Response.Write(@" <html> <head> <link href='/Content/bootstrap/css/bootstrap.min.css' rel='stylesheet' /> <script src='/Content/jquery-1.9.1.min.js'></script> <script src='/Content/bootstrap/js/bootstrap.min.js'></script> </head> <body> <div class='panel-body' style='padding-bottom:0px;'> <div class='panel panel-primary'> <div class='panel-heading'>bootstrap表格</div> <div class='panel-body'> <table id='tbarrivequeue' class='table table-bordered table-striped'> <thead> <tr> <th>用戶ID</th> <th>用戶名</th> <th>年齡</th> <th>地址</th> <th>備註</th> </tr> </thead> <tbody> " + strUser + @" </tbody> </table> </div> </div> </div> </div> </body> </html>");
獲得結果:
按照MVC的機制,咱們的Swift.MVC裏面「M」和「C」都有了,就差「V」了,等有時間咱們也來封裝一個本身的「V」。
有了第二個版本的支持,博主已經對MVC的原理有了一個清晰的認識。在第三個版本里面,博主打算不用System.Web.Routing裏面的屬性和方法,徹底本身去解析請求,封裝上下文,執行MVC,這樣纔算是真正意義上本身的MVC。考慮到篇幅的問題,也給博主一些準備時間,第三個版本留在下篇發,有興趣的園友能夠先看看版本二,若是你能透徹理解版本二里面的原理,相信你對MVC 已經有一個清晰的認識了。
至此,此篇到此結束,版本二里面咱們MvcHandler基本上是徹底重寫的,雖然不少原理是參考MVC源碼裏面來進行的,可是它卻和源碼已經沒有任何聯繫。而UrlRoutingModule部分仍然使用的System.Web.Routing裏面的組件去解析路由的,這個將在第三個版本里面完善。源碼已經在github上面開源,有興趣能夠看看:源碼下載
若是你以爲本文可以幫助你,能夠右邊隨意 打賞 博主,也能夠 推薦 進行精神鼓勵。你的支持是博主繼續堅持的不懈動力。
本文原創出處:http://www.cnblogs.com/landeanfen/
歡迎各位轉載,可是未經做者本人贊成,轉載文章以後必須在文章頁面明顯位置給出做者和原文鏈接,不然保留追究法律責任的權利