1
public
IDisposable GetReadLock()
2
{
3
this
._rwLock.AcquireReaderLock(
-
1
);
4
return
new
ReadLockDisposable(
this
._rwLock);
5
}
AcquireReaderLock方法去请求得到该读写锁,并且设置超时时间为Infinite(无限),当using方法域结束后将释放该读写锁。
(另:ReaderWriterLock 用于同步对资源的访问。在任一特定时刻,它允许多个线程同时进行读访问,或者允许单个线程进行写访问。在资源不经常发生更改的情况下,ReaderWriterLock 所提供的吞吐量比简单的一次只允许一个线程的锁(如 Monitor)更高。)
接着从routes遍历所有的Route类,在这里我们改变它的路由处理程序,该路由处理程序类的接口为IRouteHandler,用RouteMonitor自带的DebugRouteHandler去替换它原有的RouteHandler,以便后面改变Http处理程序的“方向”。
我们先接着看后面的代码,这里有个routes.Add(DebugRoute.Singleton),DubugRoute继承于Route类,它的构造函数实现于构造可捕获所有URL地址的Route。DebugRoute.Singleton作为单一实例,代码如下:
1
public
class
DebugRoute : Route
2
{
3
private
static
DebugRoute singleton
=
new
DebugRoute();
4
5
//
可捕获所有的URL地址的Route
6
private
DebugRoute()
7
:
base
(
"
{*catchall}
"
,
new
DebugRouteHandler())
8
{
9
}
10
11
public
static
DebugRoute Singleton
12
{
13
get
14
{
15
return
singleton;
16
}
17
}
18
}
4. 接着分析DebugRouteHandler的路由处理程序:
1
public
class
DebugRouteHandler : IRouteHandler
2
{
3
public
IHttpHandler GetHttpHandler(RequestContext requestContext)
4
{
5
DebugHttpHandler handler
=
new
DebugHttpHandler();
6
handler.RequestContext
=
requestContext;
7
return
handler;
8
}
9
}
这样它可以获得实现IHttpHanlder接口的DebugHttpHandler类的实例化对象,这个实例化对象中也传入了一个RequestContext 对象实例。
5. 最后看下这个以IHttpHanlder为接口的DebugHttpHandler类,用于进行Http处理的程序:
1
public
void
ProcessRequest(HttpContext context)
2
{
3
string
format
=
"
<html>\r\n<head>\r\n <title>路由监测</title>\r\n <style>\r\n body, td, th {{font-family: verdana; font-size: .8em;}}\r\n caption {{font-weight: bold;}}\r\n tr.header {{background-color: #ffc;}}\r\n label {{font-weight: bold; }}\r\n .false {{color: #c00;}}\r\n .true {{color: #0c0;}}\r\n </style>\r\n</head>\r\n<body>\r\n<div id=\
"
main\
"
>\r\n <p class=\
"
message\
"
>\r\n 在浏览器中键入请求地址,可以监测匹配的路由。\r\n </p>\r\n <p><label>Route</label>: {1}</p>\r\n <div style=\
"
float
: left;\
"
>\r\n <table border=\
"
1
\
"
cellpadding=\
"
3
\
"
cellspacing=\
"
0
\
"
width=\
"
300
\
"
>\r\n <caption>Route Data</caption>\r\n <tr class=\
"
header\
"
><th>Key</th><th>Value</th></tr>\r\n {0}\r\n </table>\r\n </div>\r\n <div style=\
"
float
: left; margin
-
left: 10px;\
"
>\r\n <table border=\
"
1
\
"
cellpadding=\
"
3
\
"
cellspacing=\
"
0
\
"
width=\
"
300
\
"
>\r\n <caption>Data Tokens</caption>\r\n <tr class=\
"
header\
"
><th>Key</th><th>Value</th></tr>\r\n {4}\r\n </table>\r\n </div>\r\n <hr style=\
"
clear: both;\
"
/>\r\n <table border=\
"
1
\
"
cellpadding=\
"
3
\
"
cellspacing=\
"
0
\
"
>\r\n <caption>All Routes</caption>\r\n <tr class=\
"
header\
"
>\r\n <th>Matches Current Request</th>\r\n <th>Url</th>\r\n <th>Defaults</th>\r\n <th>Constraints</th>\r\n <th>DataTokens</th>\r\n </tr>\r\n {2}\r\n </table>\r\n <hr />\r\n <strong>AppRelativeCurrentExecutionFilePath</strong>: {3}\r\n</div>\r\n</body>\r\n</html>
"
;
4
string
str2
=
string
.Empty;
5
6
//
RouteData类包含所请求路由的相关值
7
RouteData routeData
=
this
.RequestContext.RouteData;
8
9
//
获得路由的URL参数值和默认值的集合
10
RouteValueDictionary values
=
routeData.Values;
11
12
//
获取路由的对象
13
RouteBase base2
=
routeData.Route;
14
15
string
str3
=
string
.Empty;
16
using
(RouteTable.Routes.GetReadLock())
17
{
18
foreach
(RouteBase base3
in
RouteTable.Routes)
19
{
20
//
返回有关集合中与指定值匹配的路由的信息,如果为空,说明不匹配
21
bool
flag
=
base3.GetRouteData(
this
.RequestContext.HttpContext)
!=
null
;
22
string
str4
=
string
.Format(
"
<span class=\
"
{
0
}\
"
>{0}</span>
"
, flag);
23
string
url
=
"
n/a
"
;
24
string
str6
=
"
n/a
"
;
25
string
str7
=
"
n/a
"
;
26
string
str8
=
"
n/a
"
;
27
Route route
=
base3
as
Route;
28
29
//
如果路由不为空
30
if
(route
!=
null
)
31
{
32
//
得到匹配的Url路由
33
url
=
route.Url;
34
35
//
得到默认的Url匹配规则信息
36
str6
=
FormatRouteValueDictionary(route.Defaults);
37
//
得到约束的Url匹配规则信息
38
str7
=
FormatRouteValueDictionary(route.Constraints);
39
//
得到命名空间的Url匹配规则信息
40
str8
=
FormatRouteValueDictionary(route.DataTokens);
41
}
42
str3
=
str3
+
string
.Format(
"
<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{3}</td></tr>
"
,
new
object
[] { str4, url, str6, str7, str8 });
43
}
44
}
45
string
str9
=
"
n/a
"
;
46
string
str10
=
""
;
47
48
//
如果只被{@cacheall}捕获时,提示不匹配
49
if
(base2
is
DebugRoute)
50
{
51
str9
=
"
<strong class=\
"
false
\
"
>NO MATCH!</strong>
"
;
52
}
53
else
54
{
55
//
匹配的路由信息
56
foreach
(
string
str11
in
values.get_Keys())
57
{
58
str2
=
str2
+
string
.Format(
"
\t<tr><td>{0}</td><td>{1} </td></tr>
"
, str11, values.get_Item(str11));
59
}
60
foreach
(
string
str11
in
routeData.DataTokens.get_Keys())
61
{
62
str10
=
str10
+
string
.Format(
"
\t<tr><td>{0}</td><td>{1} </td></tr>
"
, str11, routeData.DataTokens.get_Item(str11));
63
}
64
Route route2
=
base2
as
Route;
65
if
(route2
!=
null
)
66
{
67
str9
=
route2.Url;
68
}
69
}
70
context.Response.Write(
string
.Format(format,
new
object
[] { str2, str9, str3, context.Request.AppRelativeCurrentExecutionFilePath, str10 }));
71
}
通过它ProcessRequest来处理请求,最后呈现路由检测的页面。
从中可以看到,首先从RequestContext.RouteData可以得到RouteData类,RouteData类包含所请求路由的相关值。
从RouteData.Values获取路由的 URL 参数值和默认值的集合。
从routeData.Route获取路由的对象。
GetRouteData的方法获取有关集合中与指定值匹配的路由的信息。
通过调用FormatRouteValueDictionary方法得到每一条路由的相关值:
1
private
static
string
FormatRouteValueDictionary(RouteValueDictionary values)
2
{
3
if
(values
==
null
)
4
{
5
return
"
(null)
"
;
6
}
7
string
str
=
string
.Empty;
8
//
遍历路由键/值对的集合
9
foreach
(
string
str2
in
values.get_Keys())
10
{
11
str
=
str
+
string
.Format(
"
{0} = {1},
"
, str2, values.get_Item(str2));
12
}
13
if
(str.EndsWith(
"
,
"
))
14
{
15
str
=
str.Substring(
0
, str.Length
-
2
);
16
}
17
return
str;
18
}
通过重写
context.Response.Write(string.Format(format, new object[] { str2, str9, str3, context.Request.AppRelativeCurrentExecutionFilePath, str10 }));
页面中就呈现出路由匹配的检测信息了。