People who often read my blog may know that I am a person who prefers tips to implement a function. For example, it took a lot of time to define the blog's skin, but also to enrich the effect. Of course, the most important thing is to extract a small number of functions from the framework or class library for use, saving time for self-development. This is actually a type of reuse, especially when developing some "extensions". For example, if I tried to add the upload function for UpdatePanel, although the final result is not very satisfactory, however, most of the Hack and frontend and backend interactions are very successful. The biggest problem is cross-browser iframe communication ). Now, I plan to summarize this simple technique and reference resources for future articles.
Introduction and implementation of URL parsing in ASP. NET Routing
This time we want to "reuse" the content is the "Resolution URL" function in ASP. net url Routing. Specifically, a string is split into key/value pairs based on the specified Pattern. According to the results of. NET Reflector decompiling System. Web. Routing. dll, the parsing work is done by RouteParser and ParsedRoute. Here we will reference the relevant code. If you are interested, you can also read their complete implementation:
- 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);
-
- ...
- }
-
- ...
- }
The Code shows that RouteParser is used to convert a Pattern such as "{controller}/{action}/{id}" into a "parser ", the parser is the ParsedRoute class. When you need to split a URL string such as "Home/Index/5"), you will call the Match method of the ParsedRoute class to obtain a RouteValueDictionary object, it contains the names defined in Pattern and mappings between some values.
You may also be able to easily implement this function, but since Microsoft has already helped us, we may wish to use it directly, and occasionally it is quite convenient to split strings. Unfortunately, RouteParser and ParsedRoute are both modified by internal and cannot be accessed directly. Use tips ...... To be honest, you will find that this is the same thing, "reflection. Therefore, we will learn ASP. NET Routing practices and build two classes:
Parse two types of URLs
- internal static class RouteParser
- {
- public static ParsedRoute Parse(string routeUrl) { ... }
- }
-
- internal class ParsedRoute
- {
- public RouteValueDictionary Match(string virtualPath, RouteValueDictionary defaultValues) { ... }
- }
-
Our current practice is a kind of Hack. To ensure its maintainability, I will choose the best way to be consistent with the interface of the target class library/framework. The advantage of doing so is that I can easily understand the functions being implemented. Once there is any problem, I can directly find the corresponding internal implementation, instead of "soaring" in a pile of reflection relationships ".
Then we can achieve what we need. Here, I used FastReflectionLib to speed up the performance of reflection calls. Although I am not a Geek who is pursuing the ultimate performance, if there is a performance improvement of hundreds of times with almost no extra cost, why not?
- 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);
- }
- }
Both classes actually use reflection, get the appropriate MethodInfo from the class library, and then hand it to MethodInvoker for execution. Other ...... Because the code is too simple, I don't know what else to explain. Finally, test it with xUnit:
Test the resolution URL Effect
- 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"]);
- }
- }
To be honest, this method does not have much technical content. What we have to do is to fully match our own implementations with our goals, it seems that there are some mechanical "ing" functions. This leads to my idea. Since it is very mechanical, why not let it be completed automatically? For example, we can write a class library to achieve this effect:
- [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);
- }
By defining interfaces and tags, we can directly "declare" What types need to be "mined. Then we can naturally have a framework for matching:
- IRouteParser parser = HackFactory.Create<IRouteParser>();
- IParsedRoute route = parser.Parse("{controller}/{action}/{id}");
- RouteValueDictionary values = route.Match("Home/Index/5", null);
Is it so refreshing? Simply think about it, such a framework does not seem too difficult technically.
The above describes the "Resolution URL" function in ASP. NET Routing. This article is from Lao Zhao: reusing existing functions in the class library
- Add custom routes for ASP. net mvc applications
- Learning how to use ASP. net mvc Routing
- Analysis of URL Rewrite in ASP. NET
- Introduction to ASP. net mvc Framework
- Introduction to MvcAjaxPanel in ASP. NET MVC