Skip to content

Instantly share code, notes, and snippets.

@BrutalSimplicity
Last active June 23, 2016 07:14
Show Gist options
  • Save BrutalSimplicity/b7c1d07f5e3ec7095c34391d3b6936ba to your computer and use it in GitHub Desktop.
Save BrutalSimplicity/b7c1d07f5e3ec7095c34391d3b6936ba to your computer and use it in GitHub Desktop.
A class for Caching data across multiple threads. This was used to allow better communication among threads via a shared memory cache.
/// <summary>
/// This class caches data involved in rating. It uses a Guid as a key
/// to the cached Rate Data. Most methods involve manipulating the cached Rate Data,
/// not the cache itself. This is useful in Rate Modules that need to reference
/// data from previous rates by the same user (i.e. Multiple Programs with Single Request).
/// </summary>
public class RateCache
{
#region Public Properties
/// <summary>
/// The cache policy for the items being saved.
/// </summary>
public CacheItemPolicy ItemCachePolicy
{
get { return m_itemCachePolicy; }
set { m_itemCachePolicy = value; }
}
/// <summary>
/// The number of items stored in the rate data
/// </summary>
public int Count
{
get { return m_rateData.Count; }
}
#endregion
/// <summary>
/// Creates a RateCache object linked by the Guid key,
/// and populates the Rate Data if cached data already exists.
/// </summary>
/// <param name="transactionGuid"></param>
public RateCache(Guid guidKey)
{
m_guidKey = guidKey.ToString();
TryGetItem(m_guidKey, out m_rateData);
}
/// <summary>
/// Adds an item to the Rate Data
/// </summary>
/// <param name="key">lookup key for the new item</param>
/// <param name="item">item to be added</param>
/// <returns>true, if it adds the key succesfully, false otherwise</returns>
public bool Add(string key, dynamic item)
{
if (m_rateData == null)
{
m_rateData = new ConcurrentDictionary<string, dynamic>();
var temp = (ConcurrentDictionary<string, dynamic>)m_cachedRateInfo.AddOrGetExisting(m_guidKey, m_rateData, ItemCachePolicy);
if (temp != null)
m_rateData = temp;
}
return m_rateData.TryAdd(key, item);
}
/// <summary>
/// Removes an item from the Rate Data, and updates the cache.
/// </summary>
/// <param name="key">Key of item to remove</param>
/// <returns>True if item is succesfully removed, false otherwise.</returns>
public bool Remove(string key)
{
dynamic temp;
if (m_rateData != null)
{
return m_rateData.TryRemove(key, out temp);
}
return false;
}
/// <summary>
/// Grabs an item from the Rate Data
/// </summary>
/// <param name="key">Key of item to retrieve</param>
/// <param name="item">Item retrieved</param>
/// <returns>True, if item retrieved successfully, false otherwise</returns>
public bool TryGet(string key, out dynamic item)
{
item = default(dynamic);
bool result = false;
if (m_rateData != null)
{
result = m_rateData.TryGetValue(key, out item);
}
return result;
}
/// <summary>
/// Updates an item in the Rate Data, and updates the cache.
/// </summary>
/// <param name="key">Key of item to update</param>
/// <param name="item">New item to replace the current</param>
/// <returns>True, if Rate Data is upated successfully, false otherwise</returns>
public bool TrySet(string key, dynamic item)
{
bool result = false;
if (m_rateData != null)
{
result = m_rateData.ContainsKey(key);
if (result)
{
m_rateData[key] = item;
}
}
return result;
}
/// <summary>
/// Exports the RateData as a string with key and item separators.
/// For example (w/ default values): "key1|value+key2|value+key3|value"
/// </summary>
/// <param name="keySeparator">[Optional] Key/Item separator (Default = "|")</param>
/// <param name="itemSeparator">[Optional] Key-Item pair separator (Default = "+")</param>
/// <param name="ignorePrefix">[Optional] Prefix of items to ignore (Default = "_")</param>
/// <returns>String of key-item pairs</returns>
public string ExportRateData(string keySeparator = "|", string itemSeparator="+", string ignorePrefix = "_")
{
return string.Join(itemSeparator, m_rateData.Where(item => !item.Key.StartsWith("_"))
.Select(item => item.Key + keySeparator + item.Value.ToString()));
}
/// <summary>
/// Exports the RateData as a string with key and item separators.
/// For example (w/ default values): "key1|value+key2|value+key3|value"
/// </summary>
/// <param name="selector">Selector to return item as a string</param>
/// <param name="keySeparator">[Optional] Key/Item separator (Default = "|")</param>
/// <param name="itemSeparator">[Optional] Key-Item pair separator (Default = "+")</param>
/// <param name="ignorePrefix">[Optional] Prefix of items to ignore (Default = "_")</param>
/// <returns>String of key-item pairs</returns>
public string ExportRateData(Func<dynamic, string> selector, string keySeparator = "|", string itemSeparator = "+", string ignorePrefix = "_")
{
return string.Join(itemSeparator, m_rateData.Where(item => !item.Key.StartsWith("_"))
.Select(item => item.Key + keySeparator + selector(item)));
}
private bool TryGetItem(string key, out ConcurrentDictionary<string, dynamic> data)
{
var temp = (ConcurrentDictionary<string, dynamic>)m_cachedRateInfo.Get(key);
data = temp;
return (temp != null);
}
#region Private Declarations
private MemoryCache m_cachedRateInfo = MemoryCache.Default;
private string m_guidKey;
private CacheItemPolicy m_itemCachePolicy = new CacheItemPolicy()
{
SlidingExpiration = new TimeSpan(0, 1, 0)
};
private ConcurrentDictionary<string, dynamic> m_rateData;
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment