入口
public ActionResult CategoryNavigation(int currentCategoryId, int currentProductId)
{
string cacheKey = string.Format(ModelCacheEventConsumer.CATEGORY_NAVIGATION_MODEL_KEY, currentCategoryId, currentProductId, _workContext.WorkingLanguage.Id);
var cacheModel = _cacheManager.Get(cacheKey, () =>
{
var currentCategory = _categoryService.GetCategoryById(currentCategoryId);
...
return model;
});
return PartialView(cacheModel);
}
功能描述:
1,生成cacheKey
2, 调用_cacheManager获取数据
接下来,看看_cacheManager Get方法是如何定义的。
_cacheManager.Get定义
public static class CacheExtensions { public static T Get<T>(this ICacheManager cacheManager, string key, int cacheTime, Func<T> acquire) { if (cacheManager.IsSet(key)) { return cacheManager.Get<T>(key); } else { var result = acquire(); //if (result != null) cacheManager.Set(key, result, cacheTime); return result; } } }
由定义可知,当从缓存存中取不到数据时,则执行匿名函数acquire获取数据。
获取数据成功后,设置缓存,这样下次就可以直接从缓存中获取数据了。
Get方法中调用的是ICacheManager接口的方法,因此需要看看是哪个类实现了该接口。方法是通过查找IoC注册,找到实现ICacheManager接口的类。
接口注册
//DependencyRegistrar
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder)
{
builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance();
...
}
功能描述:在IoC容器中把MemoryCacheManager注册为ICacheManager,并且命名为nop_cache_static。
namespace Nop.Web.Infrastructure { public class DependencyRegistrar : IDependencyRegistrar { public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder) { builder.RegisterType<CatalogController>().WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static")); } } }
功能描述:在IoC容器中注册CatalogController,并把它的缓存策略设置为nop_cache_static。
完成这两步注册后,在“入口”代码块中,当需要_cacheManager实例时,IoC容器将返回MemoryCacheManager的实例。
最后看看MemoryCacheManager具体是如何缓存的。
MemoryCacheManager实现
namespace Nop.Core.Caching { public partial class MemoryCacheManager : ICacheManager { protected ObjectCache Cache { get { return MemoryCache.Default; } } public void Set(string key, object data, int cacheTime) { if (data == null) return; var policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime); Cache.Add(new CacheItem(key, data), policy); } } }
由上可知,它采用的是MemoryCache来做缓存的。
扩充知识-关于MemoryCache
Since its first release, ASP.NET has included a powerful in-memory object cache (Cache). The cache implementation has been so popular that it has been used in non-Web applications. However, it is awkward for a Windows Forms or WPF application to include a reference to System.Web.dll just to be able to use the ASP.NET object cache. To make caching available for all applications, the .NET Framework 4 introduces a new assembly, a new namespace, some base types, and a concrete caching implementation. The new System.Runtime.Caching.dll assembly contains a new caching API in the System.Runtime.Caching namespace. The namespace contains two core sets of classes: Abstract types that provide the foundation for building any type of custom cache implementation. A concrete in-memory object cache implementation (the MemoryCache class).
The new MemoryCache class is modeled closely on the ASP.NET cache, and it shares much of the internal cache engine logic with ASP.NET. Although the public caching APIs in the System.Runtime.Caching namespace have been updated to support development of custom caches, if you have used the ASP.NET Cache object, you will find familiar concepts in the new APIs.