patterncsharpMinor
HTTPCache and MemoryCache cross dependency
Viewed 0 times
crosshttpcachedependencymemorycacheand
Problem
After asking a question on StackOverflow about the two .NET caching systems taking dependencies on each other I gave implementing them a go. I posted them as my own answer there but before accepting the answer I'd like some second opinions on the implementations.
HttpCacheChangeMonitor
Allows ObjectCache items to take a dependency on HTTPCache
Test
```
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 da
HttpCacheChangeMonitor
Allows ObjectCache items to take a dependency on 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);
}
}Test
```
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 da
Solution
Overall looks very good, clean and well done. I only see minor tiny little things...
Nitpick - "Initialise" vs "Initialize"
This is just a minor nitpick, but it's kind of jumping at me:
I find it weird that a method called
Also the MSDN for
But then again it's no biggie, the code is very clear and easy to follow.
Temporal Coupling
That said I like constructors that do very little, and this is what you've got here, but the
I'd expect it to blow up. One way to eliminate the temporal coupling, would be to take the array as a parameter:
...and then the order of operations doesn't matter anymore:
(haven't looked at the test code)
Nitpick - "Initialise" vs "Initialize"
This is just a minor nitpick, but it's kind of jumping at me:
private void Initialise()
{
HttpRuntime.Cache.Add(_uniqueId, _uniqueId, new CacheDependency(null, _httpCacheKeys), DateTime.MaxValue, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, Callback);
InitializationComplete();
}I find it weird that a method called
Initialise() is calling one that's called InitializationComplete() - I think for consistency it would be better named Initialize().Also the MSDN for
InitializationComplete() says it's called from the constructor of derived classes to indicate that initialization is finished. - you are calling it from within the constructor, and I'm not familiar with using the ChangeMonitor class but it might be clearer to have that call explicitly show up in the constructor (similar to how InitializeComponents() remains in a form's constructor no matter what):public HttpCacheChangeMonitor(string[] httpCacheKeys)
{
_httpCacheKeys = httpCacheKeys;
Initialize();
InitializationComplete();
}But then again it's no biggie, the code is very clear and easy to follow.
Temporal Coupling
That said I like constructors that do very little, and this is what you've got here, but the
Initialise method seems of very little use, and has temporal coupling with the setting of _httpCacheKeys - I mean, if your constructor looked like this:public HttpCacheChangeMonitor(string[] httpCacheKeys)
{
Initialise();
_httpCacheKeys = httpCacheKeys;
}I'd expect it to blow up. One way to eliminate the temporal coupling, would be to take the array as a parameter:
private void Initialize(string[] httpCacheKeys)
{
HttpRuntime.Cache.Add(_uniqueId, _uniqueId, new CacheDependency(null, httpCacheKeys), DateTime.MaxValue, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, Callback);
InitializationComplete();
}...and then the order of operations doesn't matter anymore:
public HttpCacheChangeMonitor(string[] httpCacheKeys)
{
Initialize(httpCacheKeys);
_httpCacheKeys = httpCacheKeys;
}(haven't looked at the test code)
Code Snippets
private void Initialise()
{
HttpRuntime.Cache.Add(_uniqueId, _uniqueId, new CacheDependency(null, _httpCacheKeys), DateTime.MaxValue, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, Callback);
InitializationComplete();
}public HttpCacheChangeMonitor(string[] httpCacheKeys)
{
_httpCacheKeys = httpCacheKeys;
Initialize();
InitializationComplete();
}public HttpCacheChangeMonitor(string[] httpCacheKeys)
{
Initialise();
_httpCacheKeys = httpCacheKeys;
}private void Initialize(string[] httpCacheKeys)
{
HttpRuntime.Cache.Add(_uniqueId, _uniqueId, new CacheDependency(null, httpCacheKeys), DateTime.MaxValue, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, Callback);
InitializationComplete();
}public HttpCacheChangeMonitor(string[] httpCacheKeys)
{
Initialize(httpCacheKeys);
_httpCacheKeys = httpCacheKeys;
}Context
StackExchange Code Review Q#47488, answer score: 3
Revisions (0)
No revisions yet.