新聞中心
經(jīng)??次也┛偷娜丝赡軙?,我是一個喜歡搞點小技巧來實現(xiàn)某個功能的人。例如博客的皮膚,自己花了不少時間定義,也是為了效果豐富一些。當(dāng)然,搞得最多的是從框架或類庫內(nèi)部取出一點小功能來用用,節(jié)省自己開發(fā)的時間。這其實也是一種復(fù)用,尤其是開發(fā)一些“擴(kuò)展”的時候,例如當(dāng)時嘗試為UpdatePanel增加上傳功能,雖然最后的結(jié)果不是很理想,但是大部分的Hack以及前后端的交互是非常成功的(最大的問題在于跨瀏覽器實現(xiàn)iframe通信)。而現(xiàn)在也打算總結(jié)一次這方面的簡單技巧,為以后的文章貢獻(xiàn)點引用資源。

創(chuàng)新互聯(lián)建站是專業(yè)的朗縣網(wǎng)站建設(shè)公司,朗縣接單;提供成都網(wǎng)站設(shè)計、網(wǎng)站制作,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行朗縣網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊,希望更多企業(yè)前來合作!
ASP.NET Routing中解析URL功能介紹與實現(xiàn)
這次我們想“復(fù)用”的內(nèi)容是ASP.NET URL Routing中“解析URL”的功能。具體一點地說,就是把一個字符串根據(jù)指定的Pattern拆分成鍵/值對的功能。從.NET Reflector反編譯System.Web.Routing.dll的結(jié)果來看,這部分的解析工作是交由RouteParser和ParsedRoute兩個類完成的。這里引用一下相關(guān)的使用代碼,如果您感興趣的話,也可以閱讀它們完整的實現(xiàn):
- public class Route
- {
- public string Url
- {
- get { ... }
- set
- {
- this._parsedRoute = RouteParser.Parse(value);
- this._url = value;
- }
- }
- public override RouteData GetRouteData(HttpContextBase httpContext)
- {
- string virtualPath = ...
- RouteValueDictionary values = this._parsedRoute.Match(virtualPath, this.Defaults);
- ...
- }
- ...
- }
從代碼中可以看出,RouteParser的作用是將一個Pattern(如"{controller}/{action}/{id}")轉(zhuǎn)化成一個“解析器”,而這個解析器便是ParsedRoute類。在需要拆分一個URL字符串(如"Home/Index/5")的時候,便會調(diào)用ParsedRoute類的Match方法,由此得到一個RouteValueDictionary對象,其中包含了Pattern中定義的名稱,和一些值的映射關(guān)系。
可能您也能夠輕易實現(xiàn)這樣的功能,不過既然微軟已經(jīng)幫我們做好了,我們也不妨直接使用一下,偶爾用來拆拆字符串也是挺方便的。只可惜RouteParser和ParsedRoute都是由internal修飾的,我們無法直接訪問到。那么就用點小技巧吧……說實話,其實您會發(fā)現(xiàn)也就這么一回事,“反射”罷了。因此,我們便學(xué)著ASP.NET Routing的做法,構(gòu)建兩個類吧:
解析URL的兩個類
- internal static class RouteParser
- {
- public static ParsedRoute Parse(string routeUrl) { ... }
- }
- internal class ParsedRoute
- {
- public RouteValueDictionary Match(string virtualPath, RouteValueDictionary defaultValues) { ... }
- }
我們目前的做法算是一種Hack,為了保證其可維護(hù)性,我會選擇與目標(biāo)類庫/框架的接口盡可能完全一致的做法。這么做的好處在于,我可以很輕易地理解正在實現(xiàn)的功能,一旦出現(xiàn)了任何問題,就可以直接去找對應(yīng)的內(nèi)部實現(xiàn),而不用在一堆堆的反射關(guān)系中“翱翔”。
接著便可以實現(xiàn)我們需要的效果了。在這里,我使用了FastReflectionLib來加快反射調(diào)用的性能。雖然我不是一個追求性能極致的Geek,但是如果有一種幾乎不耗費額外代價,就能得到數(shù)百倍的性能提升,何樂而不為呢?
- internal static class RouteParser
- {
- private static MethodInvoker s_parseInvoker;
- static RouteParser()
- {
- var parserType = typeof(Route).Assembly.GetType("System.Web.Routing.RouteParser");
- var parseMethod = parserType.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public);
- s_parseInvoker = new MethodInvoker(parseMethod);
- }
- public static ParsedRoute Parse(string routeUrl)
- {
- return new ParsedRoute(s_parseInvoker.Invoke(null, routeUrl));
- }
- }
- internal class ParsedRoute
- {
- private static MethodInvoker s_matchInvoker;
- static ParsedRoute()
- {
- var routeType = typeof(Route).Assembly.GetType("System.Web.Routing.ParsedRoute");
- var matchMethod = routeType.GetMethod("Match", BindingFlags.Instance | BindingFlags.Public);
- s_matchInvoker = new MethodInvoker(matchMethod);
- }
- private object m_instance;
- public ParsedRoute(object instance)
- {
- this.m_instance = instance;
- }
- public RouteValueDictionary Match(string virtualPath, RouteValueDictionary defaultValues)
- {
- return (RouteValueDictionary)s_matchInvoker.Invoke(this.m_instance, virtualPath, defaultValues);
- }
- }
兩個類其實都是使用反射,從類庫中獲取合適的MethodInfo,然后交給MethodInvoker去執(zhí)行。其他的……由于代碼過于簡單,我都不知道還需要解釋什么東西。最后就使用xUnit測試一下吧:
解析URL效果測試
- public class ParseRouteTest
- {
- [Fact]
- public void Basic_Parsing()
- {
- var parsedRoute = RouteParser.Parse("{controller}/{action}/{id}");
- var values = parsedRoute.Match("Home/Index/5", null);
- Assert.Equal("Home", values["controller"]);
- Assert.Equal("Index", values["action"]);
- Assert.Equal("5", values["id"]);
- }
- }
說實話,這個方法并沒有太多技術(shù)含量,由于我們將自己的實現(xiàn)和目標(biāo)實現(xiàn)完全對應(yīng)起來,所以我們所要做的,似乎也都是些機械的“映射”功能而已。這就引發(fā)了我的一個想法,既然很“機械”,那么為什么不去讓它“自動”完成呢?例如,我們完全可以寫一個類庫,來實現(xiàn)這樣的效果:
- [Type("System.Web.Routing.ParsedRoute, ...")]
- interface IParsedRoute
- {
- RouteValueDictionary Match(string virtualPath, RouteValueDictionary defaultValues);
- }
- [Type("System.Web.Routing.RouteParser, ...")]
- interface IRouteParser
- {
- [Static]
- IParsedRoute Parse(string url);
- }
通過定義接口和標(biāo)記,我們可以直接“聲明”需要“挖掘”出來的類型是什么。然后自然可以有框架為我們進(jìn)行匹配:
- IRouteParser parser = HackFactory.Create
(); - IParsedRoute route = parser.Parse("{controller}/{action}/{id}");
- RouteValueDictionary values = route.Match("Home/Index/5", null);
是不是一下子變得爽快了許多?簡單想了想,這樣的框架從技術(shù)上來說似乎并沒有太多困難。
以上就對ASP.NET Routing中的“解析URL”功能進(jìn)行了介紹。本文來自老趙點滴:《復(fù)用類庫內(nèi)部已有功能》
網(wǎng)站標(biāo)題:ASP.NETRouting之“解析URL”功能詳解
新聞來源:http://www.dlmjj.cn/article/djedicj.html


咨詢
建站咨詢
