该类型继承自字典接口IDictionary<string,object>,继承自字典接口而不是继承自字典基类目的只是想使用字典的行为而不是它的默认实现;在RouteValueDictionary内部使用了一个Dictionary<string,object>类型作为最终容器;
Dictionary<string,object> d = new Dictionary<string,object> (CaseInsensitiveStringComparer.Instance);
在构造函数中使用了一个内部类CaseInsensitiveStringComparer进行Key的相等比较:
internal class CaseInsensitiveStringComparer : IEqualityComparer<string> { public static readonly CaseInsensitiveStringComparer Instance = new CaseInsensitiveStringComparer (); public int GetHashCode (string obj) { return obj.ToLower (CultureInfo.InvariantCulture).GetHashCode (); } public bool Equals (string obj1, string obj2) { return String.Equals (obj1, obj2, StringComparison.OrdinalIgnoreCase); } }
IEqualityComparer接口还是很不错的,不过现在基本上不这么用了,而是直接提供了一个Lambda做为比较函数;
【RouteData】
路由数据对象,它的大概意思我想大家应该知道了,上面提到过很多次,这里就不介绍了;我们直接看一下RouteData内部核心代码段:
public RouteData (RouteBase route, IRouteHandler routeHandler) { Route = route; RouteHandler = routeHandler; DataTokens = new RouteValueDictionary (); Values = new RouteValueDictionary (); } public RouteValueDictionary DataTokens { get; private set; } public RouteBase Route { get; set; } public IRouteHandler RouteHandler { get; set; } public RouteValueDictionary Values { get; private set; }
通过构造函数我们能了解到,保存了对Route对象的引用和IRouteHander接口的引用,为什么将IRouteHandler作为构造函数参数,那是因为RouteBase根本没有对IRouteHander接口的属性定义;IRouteHandler接口在不在RouteBase或Route中不重要,因为Route可以是自定义的,这里的强制性是在RouteData中,它的构造函数必须接受IRouteHandler类型接口;
我们接着看,在构造函数的下面两行代码中分别是实例化了DataTokens、Values两个属性,而类型是RouteValueDictionary,这也刚好和我们上面分析的对上了;RouteValueDictionary是内部用来保存这些零散键值对数据容器,在Route、RouteData还有其他地方均需要用到;就是因为RouteValueDictionary的Value是Object类型,所以可以用来存放任何类型的值,比较通用;
【RequestContext 】
RequestContext在上面也已经接触很多次了,表示请求上下文,也就是跟当请求相关的所有数据都封装在里面;在后面的文章中,我们将接触很多类似Context的对象,如:ControlContext,ViewContext之类的,都是用来控制上下文的边界,而不是直接传递零散的参数;
4.4】IRouteHandler 、IHttpHander两个接口之间的关系
IRouteHandler接口是路由框架起作用的核心,只有提供了IRouteHandler实现才能顺利的得到背后的IHttpHandler接口;ASP.NETMVC提供了MvcRouteHandler对象来实现IRouteHandler接口,MvcRouteHandler在内部实例化实现了IHttpHandler接口的MvcHandler对象;MvcHandler然后通过RequestContext对象获取RouteData对象,接着得到相应的Control信息,进行后续的执行处理;
5.】UrlRoutingHandler 对象内部结构及扩展应用
在ASP.NETRouting路由框架中有一个很重要的IHttpHandler接口对象UrlRoutingHanlder,我想你肯定很疑惑,为什么需要这样一个对象;其实它的存在是为了提供给我们绕过UrlRoutingModule模块的机会;根据上面的详细的分析,我们知道路由的入口在UrlRoutingModule,所有的路由相关的映射工作都在该类中完成,但是有时候我们很想绕过UrlRoutingModule进行简单的处理或者性能方面的优化考虑,这就派上用场了;我能想到的使用场景目前来看是对ASP.NET第版本的项目做Url重写是比较方便,首先我们的项目需要建立在低版本的ASP.NET之上,但是需要添加Url.ReWriter的功能,就需要我们自己去实现这样的功能;
但是工作量和性能都很难控制好,如果使用这里提供的UrlRoutingHandler进行实现就很方便了,UrlRoutingHandler给我们使用ASP.NETRouting框架的机会同时也不需要关心是否配置了UrlRoutingModule;
public abstract class UrlRoutingHandler : IHttpHandler
根据代码看出它是一个抽象类,直接实现IHttpHanlder接口,但是重要的是ProcessRequest方法;
protected virtual void ProcessRequest (HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException ("httpContext"); var rd = RouteCollection.GetRouteData (httpContext); if (rd == null) throw new HttpException ("The incoming request does not match any route"); if (rd.RouteHandler == null) throw new InvalidOperationException ("No IRouteHandler is assigned to the selected route"); RequestContext rc = new RequestContext (httpContext, rd); var hh = rd.RouteHandler.GetHttpHandler (rc); VerifyAndProcessRequest (hh, httpContext); } protected abstract void VerifyAndProcessRequest (IHttpHandler httpHandler, HttpContextBase httpContext);