在程序中加入缓存的目的很多是为了提高程序的性能,提高数据的查找效率,在MVC框架中也引入了非常多的缓存,比如Controller的匹配查找,Controller,ControllerDescriptorCache...大部分的缓存设计都是采用了key-value的结构;

ControllerTypeCache

ControllerTypeCache类是对应用程序集中的Controller类型进行缓存,当请求进入MVC框架中,需要根据RouteData中ControllerName 以及命名空间来进行查找出正确的Controller类型。如果程序比较大时,Controller就要对程序中所有的dll中的类进行查找匹配,效率肯定非常低下;

在MVC框架中对于Controller类的查找匹配引入了ControllerTypeCache类,在缓存类中存在Dictionary<string, ILookup<string, Type>>的缓存结构,在这个结构中key为去掉Controller后缀的Controller类型的Name,Value 值为ILookup<string, Type>结构,其中key值为命名空间名称,Value 为Controller的类型;而且这些key都是忽略大小写;

     public void EnsureInitialized(IBuildManager buildManager)
{
if (_cache == null)
{
lock (_lockObj)
{
if (_cache == null)
{
List<Type> controllerTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(TypeCacheName, IsControllerType, buildManager);
var groupedByName = controllerTypes.GroupBy(
t => t.Name.Substring(, t.Name.Length - "Controller".Length), StringComparer.OrdinalIgnoreCase);
_cache = groupedByName.ToDictionary(
g => g.Key,
g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
StringComparer.OrdinalIgnoreCase);
}
}
}
}

ControllerTypeCache类中EnsureInitialized方法就是构建缓存结构,GetFilteredTypesFromAssemblies方法时获取到应用程序集中所有的Control类型,在MVC框架中会在应用程序启动时加载所有的dll类中的Controller类型然后调用IBuildManager接口的方法CreateCachedFile方法将这些类型序列到磁盘文件中,下次请求到来时直接从磁盘文件中加载,文件名字为“MVC-ControllerTypeCache.xml”;_cache 缓存文件的地址是在HttpRuntime.CodegenDir+"//UserCache//MVC-ControllerTypeCache.xml";

ReaderWriterCache<TKey, TValue>
        ReaderWriterCache是一个读写缓存抽象类,它的缓存结构也是key-value的形式,在MVC框架中ControllerDescriptorCache类,ActionMethodDispatcherCache类都继承了这个抽象类;在ControllerDescriptorCache类中key为Controller的Type类型,Value为ControllerDescriptor类; ActionMethodDispatcherCache类中key为action方法的MethodInfo,Value为ActionMethodDispatcher类;

在ReaderWriterCache类中有个重要的读取或是设置缓存的FetchOrCreateItem的方法;

 private readonly ReaderWriterLockSlim _readerWriterLock = new ReaderWriterLockSlim();
protected TValue FetchOrCreateItem<TArgument>(TKey key, Func<TArgument, TValue> creator, TArgument state)
{
// first, see if the item already exists in the cache
_readerWriterLock.EnterReadLock();
try
{
TValue existingEntry;
if (_cache.TryGetValue(key, out existingEntry))
{
return existingEntry;
}
}
finally
{
_readerWriterLock.ExitReadLock();
} // insert the new item into the cache
TValue newEntry = creator(state);
_readerWriterLock.EnterWriteLock();
try
{
TValue existingEntry;
if (_cache.TryGetValue(key, out existingEntry))
{
// another thread already inserted an item, so use that one
return existingEntry;
}
_cache[key] = newEntry;
return newEntry;
}
finally
{
_readerWriterLock.ExitWriteLock();
}
}

在FetchOrCreateItem方法中引入了ReaderWriterLockSlim类,这个类的目的是用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问,当根据key获取vlaue值时,读取缓存时根据EnterReadLock方法加入读锁,当读取完毕后,通过ExitReadLock方法释放读锁;如果缓存没有命中,则通过调用创建类型的委托创建value并写入到缓存中,在写入缓存的之前会再次从缓存中读取,如果没有则写入,防止并发造成的重复写入;

     protected override ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)
{
// Frequently called, so ensure delegate is static
Type controllerType = controllerContext.Controller.GetType();
ControllerDescriptor controllerDescriptor = DescriptorCache.GetDescriptor(
controllerType: controllerType,
creator: ReflectedAsyncControllerDescriptor.DefaultDescriptorFactory,
state: controllerType);
return controllerDescriptor;
}

 ReflectedAttributeCache

      ReflectedAttributeCache类时缓存作用于action方法中的一些特性的列表缓存,从这个缓存中可以很快获取到对于的方法的一些特性信息,在这个缓存类的类结构也是采用的key-value的形式;

      private static readonly ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionMethodSelectorAttribute>> _actionMethodSelectorAttributeCache = new ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionMethodSelectorAttribute>>();
private static readonly ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionNameSelectorAttribute>> _actionNameSelectorAttributeCache = new ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionNameSelectorAttribute>>();
private static readonly ConcurrentDictionary<MethodInfo, ReadOnlyCollection<FilterAttribute>> _methodFilterAttributeCache = new ConcurrentDictionary<MethodInfo, ReadOnlyCollection<FilterAttribute>>(); private static readonly ConcurrentDictionary<Type, ReadOnlyCollection<FilterAttribute>> _typeFilterAttributeCache = new ConcurrentDictionary<Type, ReadOnlyCollection<FilterAttribute>>();

在ReflectedAttributeCache类中存在了4种缓存,缓存的格式都是ConcurrentDictionary类型,

_actionMethodSelectorAttributeCache 缓存:key 为action方法的MethodInfo,value为继承了ActionMethodSelectorAttribute抽象类的一些子类(HttpPostAttribute,HttpGetAttribute)的只读集合;ActionMethodSelectorAttribute类的目的是筛选请求的方式;

_actionNameSelectorAttributeCache 缓存:key 为action方法的MethodInfo,value为继承了ActionNameSelectorAttribute抽象类的一些子类(ActionNameAttribute)的只读集合;ActionMethodSelectorAttribute类的目的是筛选请求方法的名字;

_methodFilterAttributeCache 缓存:key 为action方法的MethodInfo,value为继承了FilterAttribute抽象类的一些子类的只读集合;FilterAttribute类的目的是action的过滤器特性;

_typeFilterAttributeCache 缓存:key 为Controller类的Type,value为继承了FilterAttribute抽象类的一些子类的只读集合;FilterAttribute类的目的是Controller的过滤器特性;

在ReflectedAttributeCache类中获取特性集合都是通过GetAttributes方法

  private static ReadOnlyCollection<TAttribute> GetAttributes<TMemberInfo, TAttribute>(ConcurrentDictionary<TMemberInfo, ReadOnlyCollection<TAttribute>> lookup, TMemberInfo memberInfo)
where TAttribute : Attribute
where TMemberInfo : MemberInfo
{
// Frequently called, so use a static delegate
// An inline delegate cannot be used because the C# compiler does not cache inline delegates that reference generic method arguments
return lookup.GetOrAdd( memberInfo,
CachedDelegates<TMemberInfo, TAttribute>.GetCustomAttributes);
} private static class CachedDelegates<TMemberInfo, TAttribute>
where TAttribute : Attribute
where TMemberInfo : MemberInfo
{
internal static Func<TMemberInfo, ReadOnlyCollection<TAttribute>> GetCustomAttributes = (TMemberInfo memberInfo) =>
{
return new ReadOnlyCollection<TAttribute>((TAttribute[])memberInfo.GetCustomAttributes(typeof(TAttribute), inherit: true));
};
}

  

MVC 框架中的缓存的更多相关文章

  1. 谈谈MVC项目中的缓存功能设计的相关问题

    本文收集一些关于项目中为什么需要使用缓存功能,以及怎么使用等,在实际开发中对缓存的设计的考虑 为什么需要讨论缓存呢? 缓存是一个中大型系统所必须考虑的问题.为了避免每次请求都去访问后台的资源(例如数据 ...

  2. 找到MVC框架中前端URL与后端同步的解决方案

    基本思路: 先用URL标签生成完整的URL字符,前端动态参数的部分以适配符先填充,最后动态参数利用正则匹配进行替换. 这种方式,可以在各种MVC框架中适用,妙. 不废话,上码. var url = & ...

  3. [原]命令模式在MVC框架中的应用

    其实在项目开发中,我们使用了大量的设计模式,只是这些设计模式都封装在框架中了,如果你想要不仅仅局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之一就是命令模式,先来看看模式是如何 ...

  4. 命令模式在MVC框架中的应用

    事实上在项目开发中,我们使用了大量的设计模式,不过这些设计模式都封装在框架中了,假设你想要不只局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之中的一个就是命令模式,先来看看模式 ...

  5. asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析

    下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...

  6. 在ASP.NET MVC 框架中调用 html文件及解析get请求中的参数值

    在ASP.NET MVC 框架中调用 html文件: public ActionResult Index() { using (StreamReader sr = new StreamReader(P ...

  7. MVC框架中的值提供机制(三)

    在MVC框架中NameValueCollectionValueProvider采用一个NameValueCollection作为数据源,DictionnaryValueProvider的数据源类型自然 ...

  8. MVC框架中的值提供机制(二)

    在MVC框架中存在一些默认的值提供程序模板,这些值提供程序都是通过工厂模式类创建;在MVC框架中存在需要已Factory结尾的工厂类,在值提供程序中也存在ValueProviderFactories工 ...

  9. MVC框架中的值提供机制(一)

    在MVC框架中action方法中的Model数据的绑定的来源有很多个,可能是http请求中的get参数或是post提交的表单数据,会是json字符串或是路径中的相关数据;MVC框架中针对这些不同的数据 ...

随机推荐

  1. 系列文章(三):WAPI为无线局域网WLAN安全而生——By Me

    导读:无线局域网(又称为WLAN,Wireless Local Area Network),其应用领域不断拓展,无线接入所具有的前所未有的连接性和自动化能够为人们带来巨大的便利和商机.与此同时,在信息 ...

  2. PScc

      photoshop cc 2018破解版是Adobe公司最新版专业化CC图像处理软件,新功能超乎你的想象!photoshop cc 2018破解版新功能给力来袭,访问Lightroom照片,分享作 ...

  3. C#实现对图片文件的压缩、裁剪操作实例

    本文实例讲述了C#对图片文件的压缩.裁剪操作方法,在C#项目开发中非常有实用价值.分享给大家供大家参考.具体如下: 一般在做项目时,对图片的处理,以前都采用在上传时,限制其大小的方式,这样带来诸多不便 ...

  4. python数据可视化、数据挖掘、机器学习、深度学习 常用库、IDE等

    一.可视化方法 条形图 饼图 箱线图(箱型图) 气泡图 直方图 核密度估计(KDE)图 线面图 网络图 散点图 树状图 小提琴图 方形图 三维图 二.交互式工具 Ipython.Ipython not ...

  5. 关于python中的查询数据库内容中用到的fetchone()函数和fetchall()函数(转)还有fetchmany()

    最近在用python操作mysql数据库时,碰到了下面这两个函数,标记一下: fetchone() : 返回单个的元组,也就是一条记录(row),如果没有结果 则返回 None fetchall() ...

  6. Oracle_trunc截取函数

    转:http://blog.sina.com.cn/s/blog_6b58d2fa0100r6ub.html TRUNC函数用于对值进行截断. 用法有两种:TRUNC(NUMBER)表示截断数字,TR ...

  7. 发布mvc3 遇到的HTTP错误 403.14-Forbidden Web 服务器被配置为不列出此目录的内容

    今天在发布别人提供的MVC3的程序,正常部署后浏览报错,错误内容如图: 根据IIS提供的解决办法,启用目录浏览,刷新页面发现确实不报错了,但页面是以目录显示的,如图 虽然解决了报错问题,但不是正常的效 ...

  8. PL/SQL编程—控制语句

      SQL> create or replace procedure sp_pro5(id_in varchar2) is v_sal mytest.salary%type; begin sel ...

  9. akka框架地址

    http://doc.akka.io/docs/akka/2.2.3/AkkaJava.pdf

  10. 【Flask】Flask上下文

    # 上下文: ### Local对象:在`Flask`中,类似于`request`的对象,其实是绑定到了一个`werkzeug.local.Local`对象上.这样,即使是同一个对象,那么在多个线程中 ...