程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> System.Web.Routing命名空間代碼解析(三) RouteCollection類

System.Web.Routing命名空間代碼解析(三) RouteCollection類

編輯:關於ASP.NET

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();
      }
    }
  }
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved