2014-04-17 4 views
0

내 프로젝트는 대부분 .net MemoryCache를 사용하지만 HTTPCache를 사용하는 구성 요소가 있습니다. 이것은 상호 종속성을 다루기가 훨씬 더 어렵게 만듭니다.HTTPCache 및 MemoryCache 상호 종속성

어쨌든 두 캐시가 서로에 대한 종속성을 가질 수 있습니까? 예를 들어 MemoryCache에 줄 수있는 HTTPCacheChangeMonitor와 HTTPCache에 줄 수있는 MemoryCacheDependency가 있습니다.

답변

0

이 질문을 게시 한 이래로 일부 크로스 캐시 종속성을 구현하는 중입니다. 그들이 최선의 접근법을 취하고 있는지 확실하지 않습니다. HttpCacheChangeMonitor

ObjectCache는 항목에 대한 종속성을 촬영할 수 HttpCache에

public class HttpCacheChangeMonitor : ChangeMonitor 
{ 
    private readonly string _uniqueId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); 
    private readonly string[] _httpCacheKeys; 

    public override string UniqueId 
    { 
     get { return _uniqueId; } 
    } 

    public HttpCacheChangeMonitor(string httpCacheKey) 
     : this(new[] { httpCacheKey }) { } 

    public HttpCacheChangeMonitor(string[] httpCacheKeys) 
    { 
     _httpCacheKeys = httpCacheKeys; 
     Initialise(); 
    } 

    private void Initialise() 
    { 
     HttpRuntime.Cache.Add(_uniqueId, _uniqueId, new CacheDependency(null, _httpCacheKeys), DateTime.MaxValue, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, Callback); 
     InitializationComplete(); 
    } 

    private void Callback(string key, object value, CacheItemRemovedReason reason) 
    { 
     OnChanged(null); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     Debug.WriteLine(
       _uniqueId + " notifying cache of change.", "HttpCacheChangeMonitor"); 
     HttpRuntime.Cache.Remove(_uniqueId); 
    } 
} 

테스트

public class HttpCacheChangeMonitorTests 
{ 
    [Fact] 
    public void ChangeMonitorTest() 
    { 
     HttpRuntime.Cache.Add("ChangeMonitorTest1", "", null, Cache.NoAbsoluteExpiration, new TimeSpan(0,10,0), CacheItemPriority.Normal, null); 
     HttpRuntime.Cache.Add("ChangeMonitorTest2", "", null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 10, 0), CacheItemPriority.Normal, null); 
     using (MemoryCache cache = new MemoryCache("TestCache", new NameValueCollection())) 
     { 

      // Add data to cache 
      for (int idx = 0; idx < 10; idx++) 
      { 
       cache.Add("Key" + idx, "Value" + idx, GetPolicy(idx)); 
      } 

      long middleCount = cache.GetCount(); 

      // Flush cached items associated with "NamedData" change monitors 
      HttpRuntime.Cache.Remove("ChangeMonitorTest1"); 

      long finalCount = cache.GetCount(); 

      Assert.Equal(10, middleCount); 
      Assert.Equal(5, middleCount - finalCount); 
      HttpRuntime.Cache.Remove("ChangeMonitorTest2"); 
     } 
    } 

    private static CacheItemPolicy GetPolicy(int idx) 
    { 
     string name = (idx % 2 == 0) ? "ChangeMonitorTest1" : "ChangeMonitorTest2"; 

     CacheItemPolicy cip = new CacheItemPolicy(); 
     cip.AbsoluteExpiration = System.DateTimeOffset.UtcNow.AddHours(1); 
     cip.ChangeMonitors.Add(new HttpCacheChangeMonitor(name)); 
     return cip; 
    } 
} 

MemoryCacheDependency

,

는 HttpCache에 항목 테스트를

public class MemoryCacheDependency : CacheDependency 
{ 
    private readonly string _uniqueId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); 
    private readonly IEnumerable<string> _cacheKeys; 
    private readonly MemoryCache _cache; 

    public override string GetUniqueID() 
    { 
     return _uniqueId; 
    } 

    public MemoryCacheDependency(MemoryCache cache, string cacheKey) 
     : this(cache, new[] { cacheKey }) { } 
    public MemoryCacheDependency(MemoryCache cache, IEnumerable<string> cacheKeys) 
    { 
     _cache = cache; 
     _cacheKeys = cacheKeys; 
     Initialise(); 
    } 

    private void Initialise() 
    { 
     var monitor = _cache.CreateCacheEntryChangeMonitor(_cacheKeys); 
     CacheItemPolicy pol = new CacheItemPolicy{AbsoluteExpiration = DateTime.MaxValue, Priority = CacheItemPriority.NotRemovable}; 
     pol.ChangeMonitors.Add(monitor); 
     pol.RemovedCallback = Callback; 
     _cache.Add(_uniqueId, _uniqueId, pol); 
     FinishInit(); 
    } 

    private void Callback(CacheEntryRemovedArguments arguments) 
    { 
     NotifyDependencyChanged(arguments.Source, EventArgs.Empty); 
    } 

    protected override void DependencyDispose() 
    { 
     Debug.WriteLine(
        _uniqueId + " notifying cache of change.", "ObjectCacheDependency"); 
     _cache.Remove(_uniqueId); 
     base.DependencyDispose(); 
    } 
} 

MemoryCache

public class MemoryCacheDependencyTests 
{ 
    [Fact] 
    public void CacheDependencyTest() 
    { 
     using (MemoryCache cache = new MemoryCache("TestCache", new NameValueCollection())) 
     { 
      cache.Add("HttpCacheTest1", DateTime.Now, new CacheItemPolicy {SlidingExpiration = new TimeSpan(0, 10, 0)}); 
      cache.Add("HttpCacheTest2", DateTime.Now, new CacheItemPolicy {SlidingExpiration = new TimeSpan(0, 10, 0)}); 

      // Add data to cache 
      for (int idx = 0; idx < 10; idx++) 
      { 
       HttpRuntime.Cache.Add("Key" + idx, "Value" + idx, GetDependency(cache, idx), Cache.NoAbsoluteExpiration, new TimeSpan(0,10,0), CacheItemPriority.NotRemovable, null); 
      } 

      int middleCount = HttpRuntime.Cache.Count; 

      // Flush cached items associated with "NamedData" change monitors 
      cache.Remove("HttpCacheTest1"); 

      int finalCount = HttpRuntime.Cache.Count; 

      Assert.Equal(10, middleCount); 
      Assert.Equal(5, middleCount - finalCount); 
     } 
    } 

    private static CacheDependency GetDependency(MemoryCache cache, int idx) 
    { 
     string name = (idx % 2 == 0) ? "HttpCacheTest1" : "HttpCacheTest2"; 

     return new MemoryCacheDependency(cache, name); 
    } 
} 
을 종속성을 찍을 수 있도록 허용