Skip to content

Instantly share code, notes, and snippets.

@pmunin
Last active April 18, 2017 20:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pmunin/b369f1e2555653970fc9 to your computer and use it in GitHub Desktop.
Save pmunin/b369f1e2555653970fc9 to your computer and use it in GitHub Desktop.
ObjectData extensions allow to extend any .NET objects with dynamic dictionary storage, which will be collected by GC with the associated object
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace ObjectDataUtils
{
/// <summary>
/// Allows to extend any .NET objects with dynamic dictionary storage,
/// which will be collected by GC with the associated object
/// Latest code is here: https://gist.github.com/pmunin/b369f1e2555653970fc9
/// </summary>
public static class ObjectDataExtensions
{
static readonly ConditionalWeakTable<object, ConcurrentDictionary<string, object>> dataByObject = new ConditionalWeakTable<object, ConcurrentDictionary<string, object>>();
/// <summary>
/// Retrieves the data dictionary attached to the object. Dictionary is deallocated by GC when associated object is.
/// </summary>
/// <param name="target">extended object</param>
/// <param name="createIfNotExist">create extension dictionary if it does not exist</param>
/// <returns></returns>
public static ConcurrentDictionary<string, object> Data(this object target, bool createIfNotExist = true)
{
var data = createIfNotExist ? dataByObject.GetOrCreateValue(target) : dataByObject.GetValue(target);
return data;
}
/// <summary>
/// Try get value from weak table and return default if it does not exist
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
/// <param name="conditionalWeakTable"></param>
/// <param name="key"></param>
/// <returns></returns>
static TValue GetValue<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> conditionalWeakTable,
TKey key, TValue defaultValue = default(TValue)) where TKey : class where TValue : class
{
TValue resValue = null;
if (conditionalWeakTable.TryGetValue(key, out resValue))
return resValue;
return defaultValue;
}
/// <summary>
/// Retrieves value by key attached to the object and null if value does not exist
/// </summary>
/// <param name="target"></param>
/// <param name="key"></param>
/// <returns></returns>
public static object Data(this object target, string key)
{
var objectData = target.Data(false);
if (objectData == null) return null;
object result = null;
objectData.TryGetValue(key, out result);
return result;
}
/// <summary>
/// Sets add key value pair to the object's dynamic data
/// </summary>
/// <param name="target"></param>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static object Data(this object target, string key, object value)
{
var objectData = target.Data();
objectData[key] = value;
return value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment