This example shows a simple in-memory cache implementation showing the basics of custom caching and should not be used in a production environment.
In the Documents Servic source code, replace the code inside ServiceHelper.CreateCache
with:
_cache = new MemoryCache()
MemoryCache.cs
using Leadtools.Caching;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace MyNamespace
{
public class MemoryCache : ObjectCache
{
// The cache. A concurrent dictionary of string|object
private ConcurrentDictionary<string, object> _cache = new ConcurrentDictionary<string, object>();
//
// These members must be implemented by our class and are called by the Document toolkit
//
// Our name
public override string Name
{
get
{
return "Memory Cache";
}
}
// We only support binary serialization. In reality, we do not support policies nor serialization, but we return Binary
// to inform any callers to not bother sending us any JSON data
public override CacheSerializationMode PolicySerializationMode
{
get
{
return CacheSerializationMode.Binary;
}
set
{
throw new NotSupportedException();
}
}
public override CacheSerializationMode DataSerializationMode
{
get
{
return CacheSerializationMode.Binary;
}
set
{
throw new NotSupportedException();
}
}
// We have no special extra support
public override DefaultCacheCapabilities DefaultCacheCapabilities
{
get
{
return DefaultCacheCapabilities.None;
}
}
public override CacheItem<T> AddOrGetExisting<T>(CacheItem<T> item, CacheItemPolicy policy)
{
if (item == null)
throw new ArgumentNullException("item");
// Resolve the key, remember, we do not have regions
var resolvedKey = ResolveKey(item.RegionName, item.Key);
CacheItem<T> oldItem = null;
// Try to get the old value
// Yes, save the old value to return it to the user
object oldPayload;
if (_cache.TryGetValue(resolvedKey, out oldPayload))
oldItem = new CacheItem<T>(item.Key, (T)oldPayload, item.RegionName);
// Set the new data
_cache.TryAdd(resolvedKey, item.Value);
// Return old item
return oldItem;
}
public override CacheItem<T> GetCacheItem<T>(string key, string regionName)
{
// If we have an item with this key, return it. Otherwise return null
var resolvedKey = ResolveKey(regionName, key);
CacheItem<T> item = null;
object payload;
if (_cache.TryGetValue(resolvedKey, out payload))
item = new CacheItem<T>(key, (T)payload, regionName);
return item;
}
public override bool Contains(string key, string regionName)
{
// Check if the key is in the dictionary
var resolvedKey = ResolveKey(regionName, key);
var exists = _cache.ContainsKey(resolvedKey);
return exists;
}
public override bool UpdateCacheItem<T>(CacheItem<T> item)
{
// Update the item
if (item == null)
throw new ArgumentNullException("item");
var resolvedKey = ResolveKey(item.RegionName, item.Key);
var exists = _cache.ContainsKey(resolvedKey);
if (exists)
_cache[resolvedKey] = item.Value;
return exists;
}
public override T Remove<T>(string key, string regionName)
{
// Removed if exists, return old value
var resolvedKey = ResolveKey(regionName, key);
object payload;
var removed = _cache.TryRemove(resolvedKey, out payload);
return removed ? (T)payload : default(T);
}
public override void DeleteItem(string key, string regionName)
{
// Remove if exists
var resolvedKey = ResolveKey(regionName, key);
object payload;
_cache.TryRemove(resolvedKey, out payload);
}
private static string ResolveKey(string regionName, string key)
{
// Both must me non-empty strings
if (string.IsNullOrEmpty(regionName)) throw new InvalidOperationException("Region name must be a none empty string");
if (string.IsNullOrEmpty(key)) throw new InvalidOperationException("Region key name must be a none empty string");
// We are a simple dictionary with no grouping. regionName might not be unique, key might not be unique, but combine them
// and we are guaranteed a unique key
return regionName + "-" + key;
}
public override void UpdatePolicy(string key, CacheItemPolicy policy, string regionName)
{
// Nothing to do
}
//
// These members must be over implemented by our class but are never called by the Document toolkit
// So just throw a not supported exception
//
// This is for default region support. We do not have that
public override object this[string key]
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
// Delete a region in one shot. We do not support that
// Note: This is only called if we have DefaultCacheCapabilities.CacheRegions. Since we do not, the caller is responsible for
// calling DeleteAll passing all the items of the region (which in turn will call DeleteItem for each)
public override void DeleteRegion(string regionName)
{
throw new NotSupportedException();
}
// Begin adding an external resource. We do not support that
// Note: This is only called if we have DefaultCacheCapabilities.ExternalResources
public override Uri BeginAddExternalResource(string key, string regionName, bool readWrite)
{
throw new NotSupportedException();
}
// End adding an external resource. We do not support that
// Note: This is only called if we have DefaultCacheCapabilities.ExternalResources
public override void EndAddExternalResource<T>(bool commit, string key, T value, CacheItemPolicy policy, string regionName)
{
throw new NotSupportedException();
}
// Get the item external resource. We do not support that
// Note: This is only called if we have DefaultCacheCapabilities.ExternalResources
public override Uri GetItemExternalResource(string key, string regionName, bool readWrite)
{
throw new NotSupportedException();
}
// Remove the item external resource. We do not support that
// Note: This is only called if we have DefaultCacheCapabilities.ExternalResources
public override void RemoveItemExternalResource(string key, string regionName)
{
throw new NotSupportedException();
}
// Get the item virtual directory path. We do not support that
// Note: This is only called if we have DefaultCacheCapabilities.VirtualDirectory
public override Uri GetItemVirtualDirectoryUrl(string key, string regionName)
{
throw new NotSupportedException();
}
// Getting number of items in the cache. We do not support that
public override long GetCount(string regionName)
{
throw new NotSupportedException();
}
// Statistics. We do not support that
public override CacheStatistics GetStatistics()
{
throw new NotSupportedException();
}
// Statistics. We do not support that
public override CacheStatistics GetStatistics(string key, string regionName)
{
throw new NotSupportedException();
}
// Getting all the values. We do not support that
public override IDictionary<string, object> GetValues(IEnumerable<string> keys, string regionName)
{
throw new NotSupportedException();
}
// Enumeration of the items. We do not support that
protected override IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
throw new NotSupportedException();
}
// Enumeration of the keys. We do not support that
public override void EnumerateKeys(string region, EnumerateCacheEntriesCallback callback)
{
throw new NotSupportedException();
}
// Enumeration of regions. We do not support that
public override void EnumerateRegions(EnumerateCacheEntriesCallback callback)
{
throw new NotSupportedException();
}
}
}