惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threat Research - Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
A
Arctic Wolf
Security Latest
Security Latest
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Troy Hunt's Blog
Latest news
Latest news
Help Net Security
Help Net Security
S
Security Affairs
Webroot Blog
Webroot Blog
The Hacker News
The Hacker News
AI
AI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tor Project blog
Forbes - Security
Forbes - Security
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
Attack and Defense Labs
Attack and Defense Labs
P
Proofpoint News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
H
Help Net Security
L
Lohrmann on Cybersecurity
S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
MongoDB | Blog
MongoDB | Blog
Cyberwarzone
Cyberwarzone
The Last Watchdog
The Last Watchdog
S
Securelist
N
News and Events Feed by Topic
S
Secure Thoughts
F
Fortinet All Blogs
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
M
MIT News - Artificial intelligence
F
Full Disclosure
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Microsoft Security Blog
Microsoft Security Blog
I
InfoQ
P
Privacy International News Feed
L
LangChain Blog
Know Your Adversary
Know Your Adversary
C
CERT Recently Published Vulnerability Notes

博客园 - Andrew Yin

数据访问层组件设计以及选型意识流 第四次扩展的讨论 数据访问层组件设计以及选型意识流 第三次封装(极致、极简而不简单) 数据访问层组件设计以及选型意识流 第二次封装以及各种牢骚 数据访问层组件设计以及选型意识流 第一次封装 数据访问层组件设计以及选型意识流 开篇 UTF-8, Unicode, GB2312三种编码方式解析, 深入研究汉字编码 C++中的模板实例:链表模板 一步一步学Ruby系列(二):Ruby中的函数 一步一步学Ruby系列(一):Ruby基础知识 .NET下的AOP: PostSharp 原理分析 AST,DLR,Expression Tree-----------推荐一位牛人的博客! C# 交互式SHELL C#中的 eval System.Web.Routing命名空间代码解析(四) Route解析中用到的实体类,一些以"Segment”为名的类 System.Web.Routing命名空间代码解析(二) Routing类(上) System.Web.Routing命名空间代码解析(一) RouteBase类,RouteData类,RouteValueDictionary类 ASP.NET MVC中的各种上下文对象 有关string和Cookie的几个有用的扩展方法 反射加异步,根据枚举值来异步执行方法 操作Enum的一些实用方法
System.Web.Routing命名空间代码解析(三) RouteCollection类
Andrew Yin · 2008-12-05 · via 博客园 - Andrew Yin

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 getset; }

        
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();
            }

        }

    }

}