在查找資料的過程中。原來園子里面已經有過分析了。nopCommerce架構分析系列(二)數據Cache。 接下來是一些學習補充。
1.Nop中沒有System.Web.Caching.Cache的實現。原因暫不明。先自己實現一個吧
using System; using System.Collections.Generic; using System.Web; using System.Runtime.CompilerServices; using System.Web.Caching; using System.Collections; using System.Text.RegularExpressions; namespace SDF.Core.Caching { public class CacheManager : ICacheManager { System.Web.Caching.Cache Cache = HttpRuntime.Cache; public void Set(string key, object data) { Cache.Insert(key, data); } public void Set(string key, object data, DateTime absoluteExpiration, TimeSpan slidingExpiration) { Cache.Insert(key, data, null,absoluteExpiration, slidingExpiration); } public object Get(string Key) { return Cache[Key]; } public T Get<T>(string key) { return (T)Cache[key]; } public bool IsSet(string key) { return Cache[key] != null; } public void Remove(string Key) { if (Cache[Key] != null) { Cache.Remove(Key); } } public void RemoveByPattern(string pattern) { IDictionaryEnumerator enumerator = Cache.GetEnumerator(); Regex rgx = new Regex(pattern, (RegexOptions.Singleline | (RegexOptions.Compiled | RegexOptions.IgnoreCase))); while (enumerator.MoveNext()) { if (rgx.IsMatch(enumerator.Key.ToString())) { Cache.Remove(enumerator.Key.ToString()); } } } public void Clear() { IDictionaryEnumerator enumerator = Cache.GetEnumerator(); while (enumerator.MoveNext()) { Cache.Remove(enumerator.Key.ToString()); } } } }
2.MemoryCache 和 ASP.NET Cache 區別。
引用MSDN
MemoryCache 類類似於 ASP.NET Cache 類。 MemoryCache 類有許多用於訪問緩存的屬性和方法,如果您使用過 ASP.NET Cache 類,您將熟悉這些屬性和方法。 Cache 和 MemoryCache 類之間的主要區別是:MemoryCache 類已被更改,以便 .NET Framework 應用程序(非 ASP.NET 應用程序)可以使用該類。 例如,MemoryCache 類對 System.Web 程序集沒有依賴關系。 另一個差別在於您可以創建 MemoryCache 類的多個實例,以用於相同的應用程序和相同的 AppDomain 實例。
代碼更清楚一點:
[Test] public void MemoryCacheTest() { var cache = new MemoryCache("cache1"); var cache2 = new MemoryCache("cache2"); var policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(60); cache.Set(new CacheItem("key1", "data1"), policy); var obj = cache.Get("key1"); Assert.IsNotNull(obj); var obj2 = cache2.Get("key1"); Assert.IsNull(obj2); }
3.Nop中IOC和ICache
注冊CacheManager
//cache manager builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance(); builder.RegisterType<PerRequestCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_per_request").InstancePerHttpRequest();
注冊Service(可以根據實際需求為Service提供不同的緩存方式。)
//pass MemoryCacheManager to SettingService as cacheManager (cache settngs between requests) builder.RegisterType<SettingService>().As<ISettingService>() .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static")) .InstancePerHttpRequest(); //pass MemoryCacheManager to LocalizationService as cacheManager (cache locales between requests) builder.RegisterType<LocalizationService>().As<ILocalizationService>() .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static")) .InstancePerHttpRequest(); //pass MemoryCacheManager to LocalizedEntityService as cacheManager (cache locales between requests) builder.RegisterType<LocalizedEntityService>().As<ILocalizedEntityService>() .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static")) .InstancePerHttpRequest();
最后是構造器注入
/// <summary> /// Provides information about localizable entities /// </summary> public partial class LocalizedEntityService : ILocalizedEntityService { /// <summary> /// Ctor /// </summary> /// <param name="cacheManager">Cache manager</param> /// <param name="localizedPropertyRepository">Localized property repository</param> public LocalizedEntityService(ICacheManager cacheManager, IRepository<LocalizedProperty> localizedPropertyRepository) { this._cacheManager = cacheManager; this._localizedPropertyRepository = localizedPropertyRepository; } }
4.Cache的使用
一段Nop中的代碼
private const string BLOGPOST_BY_ID_KEY = "Nop.blogpost.id-{0}"; private const string BLOGPOST_PATTERN_KEY = "Nop.blogpost."; /// <summary> /// Gets a blog post /// </summary> /// <param name="blogPostId">Blog post identifier</param> /// <returns>Blog post</returns> public virtual BlogPost GetBlogPostById(int blogPostId) { if (blogPostId == 0) return null; string key = string.Format(BLOGPOST_BY_ID_KEY, blogPostId); return _cacheManager.Get(key, () => { var pv = _blogPostRepository.GetById(blogPostId); return pv; }); }/// <summary> /// Updates the blog post /// </summary> /// <param name="blogPost">Blog post</param> public virtual void UpdateBlogPost(BlogPost blogPost) { if (blogPost == null) throw new ArgumentNullException("blogPost"); _blogPostRepository.Update(blogPost); _cacheManager.RemoveByPattern(BLOGPOST_PATTERN_KEY); //event notification _eventPublisher.EntityUpdated(blogPost); }
在查找數據時,會先從緩存中讀取,更新數據時再清空緩存。 但是在這里Update了一個blogPost對象。沒有必要把所有的blogPost緩存全部清空掉。稍微改一下
/// <summary> /// Updates the blog post /// </summary> /// <param name="blogPost">Blog post</param> public virtual void UpdateBlogPostV2(BlogPost blogPost) { if (blogPost == null) throw new ArgumentNullException("blogPost"); _blogPostRepository.Update(blogPost); string key = string.Format(BLOGPOST_BY_ID_KEY, blogPost.Id); _cacheManager.Remove(key); //event notification _eventPublisher.EntityUpdated(blogPost); }
總結:nop提供了易於擴展的Cache類,以及很好的使用實踐。非常有借鑒和學習使用的意義。 只需稍微改造一下就可以用於自己的項目中。