





















RouteCollection类继承于Collection<RouteBase>并且包装了一个Dictionary<string, RouteBase>,于是它提供了二者的功能。
通过察看代码我们可以知道,Collection中和Dictionary中的数据并不完全相同。
1.有Name的Route既存于D中又存于C中,并且可以通过索引属性通过Name检索(参看Add方法)
2.没有Name的Route只存于C中
3.删除Route的时候,如果D中也存在它,则从D中也删除(参看RemoveItem方法)
4.设置Route的时候,如果D中也存在它,则从D中也删除(参看SetItem方法,这点需要特别注意)
这个类中展现了一种很好的锁机制!请参看代码中的黄色高亮部分!
本类中的其他方法以后会在 Route类(下)中讲。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Security.Permissions;
using System.Threading;
using System.Web;
using System.Web.Hosting;

namespace System.Web.Routing
{
[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class RouteCollection : Collection<RouteBase>
{
// Fields
private Dictionary<string, RouteBase> _namedMap;
private ReaderWriterLock _rwLock;
private VirtualPathProvider _vpp;

// Methods
public RouteCollection()
: this(HostingEnvironment.VirtualPathProvider) {}

public RouteCollection(VirtualPathProvider virtualPathProvider)
{
this._namedMap = new Dictionary<string, RouteBase>(StringComparer.OrdinalIgnoreCase);
this._rwLock = new ReaderWriterLock();
this._vpp = virtualPathProvider;
}

public void Add(string name, RouteBase item)
{
if (item == null)
throw new ArgumentNullException("item");
if (!string.IsNullOrEmpty(name) && this._namedMap.ContainsKey(name))
throw new ArgumentException(
string.Format(CultureInfo.CurrentUICulture, RoutingResources.RouteCollection_DuplicateName,
new object[] {name}), "name");
base.Add(item);
if (!string.IsNullOrEmpty(name))
this._namedMap[name] = item;
}

protected override void ClearItems()
{
this._namedMap.Clear();
base.ClearItems();
}

private RequestContext GetRequestContext(RequestContext requestContext)
{
if (requestContext != null)
return requestContext;
HttpContext current = HttpContext.Current;
if (current == null)
throw new InvalidOperationException(RoutingResources.RouteCollection_RequiresContext);
return new RequestContext(new HttpContextWrapper(current), new RouteData());
}

public RouteData GetRouteData(HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
if (httpContext.Request == null)
throw new ArgumentException(RoutingResources.RouteTable_ContextMissingRequest, "httpContext");
if (!this.RouteExistingFiles)
{
string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) &&
(this._vpp.FileExists(appRelativeCurrentExecutionFilePath) ||
this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
return null;
}
using (this.GetReadLock())
foreach (RouteBase base2 in this)
{
RouteData routeData = base2.GetRouteData(httpContext);
if (routeData != null)
return routeData;
}
return null;
}

private static string GetUrlWithApplicationPath(RequestContext requestContext, string url)
{
string str = requestContext.HttpContext.Request.ApplicationPath ?? string.Empty;
if (!str.EndsWith("/", StringComparison.OrdinalIgnoreCase))
str = str + "/";
return requestContext.HttpContext.Response.ApplyAppPathModifier(str + url);
}

public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
requestContext = this.GetRequestContext(requestContext);
using (this.GetReadLock())
foreach (RouteBase base2 in this)
{
VirtualPathData virtualPath = base2.GetVirtualPath(requestContext, values);
if (virtualPath != null)
{
virtualPath.VirtualPath = GetUrlWithApplicationPath(requestContext, virtualPath.VirtualPath);
return virtualPath;
}
}
return null;
}

public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values)
{
RouteBase base2;
bool flag;
requestContext = this.GetRequestContext(requestContext);
if (string.IsNullOrEmpty(name))
return this.GetVirtualPath(requestContext, values);
using (this.GetReadLock())
flag = this._namedMap.TryGetValue(name, out base2);
if (!flag)
throw new ArgumentException(
string.Format(CultureInfo.CurrentUICulture, RoutingResources.RouteCollection_NameNotFound,
new object[] {name}), "name");
VirtualPathData virtualPath = base2.GetVirtualPath(requestContext, values);
if (virtualPath == null)
return null;
virtualPath.VirtualPath = GetUrlWithApplicationPath(requestContext, virtualPath.VirtualPath);
return virtualPath;
}

protected override void InsertItem(int index, RouteBase item)
{
if (item == null)
throw new ArgumentNullException("item");
if (base.Contains(item))
throw new ArgumentException(
string.Format(CultureInfo.CurrentUICulture, RoutingResources.RouteCollection_DuplicateEntry,
new object[0]), "item");
base.InsertItem(index, item);
}

protected override void RemoveItem(int index)
{
this.RemoveRouteName(index);
base.RemoveItem(index);
}

private void RemoveRouteName(int index)
{
RouteBase base2 = base[index];
foreach (KeyValuePair<string, RouteBase> pair in this._namedMap)
if (pair.Value == base2)
{
this._namedMap.Remove(pair.Key);
break;
}
}

protected override void SetItem(int index, RouteBase item)
{
if (item == null)
throw new ArgumentNullException("item");
if (base.Contains(item))
throw new ArgumentException(
string.Format(CultureInfo.CurrentUICulture, RoutingResources.RouteCollection_DuplicateEntry,
new object[0]), "item");
this.RemoveRouteName(index);
base.SetItem(index, item);
}

// Properties
public RouteBase this[string name]
{
get
{
RouteBase base2;
if (!string.IsNullOrEmpty(name) && this._namedMap.TryGetValue(name, out base2))
return base2;
return null;
}
}

public bool RouteExistingFiles { get; set; }

public IDisposable GetReadLock()
{
this._rwLock.AcquireReaderLock(-1);
return new ReadLockDisposable(this._rwLock);
}

public IDisposable GetWriteLock()
{
this._rwLock.AcquireWriterLock(-1);
return new WriteLockDisposable(this._rwLock);
}

// Nested Types
private class ReadLockDisposable : IDisposable
{
// Fields
private ReaderWriterLock _rwLock;

// Methods
public ReadLockDisposable(ReaderWriterLock rwLock)
{
this._rwLock = rwLock;
}

void IDisposable.Dispose()
{
this._rwLock.ReleaseReaderLock();
}
}

private class WriteLockDisposable : IDisposable
{
// Fields
private ReaderWriterLock _rwLock;

// Methods
public WriteLockDisposable(ReaderWriterLock rwLock)
{
this._rwLock = rwLock;
}

void IDisposable.Dispose()
{
this._rwLock.ReleaseWriterLock();
}
}
}
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。