Created
October 21, 2016 13:25
-
-
Save ronnieoverby/80216d52c301640ebedde492d298b6df to your computer and use it in GitHub Desktop.
Mitigates Linqpad DumpContainer MemoryDump
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class MyExtensions | |
{ | |
public static void UpdateContentOccasionally(this DumpContainer dc, object newContent, int intervalMilliseconds = 1000) => | |
UpdateContentOccasionally(dc, newContent, TimeSpan.FromMilliseconds(intervalMilliseconds)); | |
public static void UpdateContentOccasionally(this DumpContainer dc, object newContent, TimeSpan interval) | |
{ | |
var swAttachment = dc.GetOrSetAttached(() => Stopwatch.StartNew()); | |
if (swAttachment.Found) | |
{ | |
if (swAttachment.Value.Elapsed >= interval) | |
{ | |
dc.UpdateContent(newContent); | |
swAttachment.Value.Restart(); | |
} | |
} | |
else | |
{ | |
dc.UpdateContent(newContent); | |
} | |
} | |
} | |
public static class AttachmentExtensions | |
{ | |
private static readonly ConditionalWeakTable<object, ConcurrentDictionary<string, object>> _attachmentTable = | |
new ConditionalWeakTable<object, ConcurrentDictionary<string, object>>(); | |
/// <summary> | |
/// Atomically gets or sets an attached value if it's found. | |
/// </summary> | |
public static AttachmentResult<T> GetOrSetAttached<T>(this object host, Func<T> factory, string key = null) | |
{ | |
key = key ?? typeof(T).AssemblyQualifiedName; | |
var dict = _attachmentTable.GetOrCreateValue(host); | |
var found = true; | |
var value = dict.GetOrAdd(key, _ => { found = false; return factory(); }); | |
var castValue = (T)value; | |
return new AttachmentResult<T>(found, castValue); | |
} | |
/// <summary> | |
/// Sets an attached value. Any existing value will be overwritten. | |
/// If a key isn't provided, the value's assembly qualified type | |
/// name will be used. | |
/// </summary> | |
public static void SetAttached(this object host, object value, string key = null) | |
{ | |
if (value == null && key == null) | |
throw new ArgumentNullException(key, $"{nameof(value)} or {nameof(key)} must be provided"); | |
key = key ?? value.GetType().AssemblyQualifiedName; | |
var dict = _attachmentTable.GetOrCreateValue(host); | |
dict[key] = value; | |
} | |
/// <summary> | |
/// Gets an attached value using the type's AssemblyQualifiedName as the key. | |
/// </summary> | |
public static AttachmentResult<object> GetAttached(this object host, Type type) => | |
GetAttached(host, type.AssemblyQualifiedName); | |
/// <summary> | |
/// Gets an attached value by name. | |
/// </summary> | |
public static AttachmentResult<object> GetAttached(this object host, string key) | |
{ | |
if (key == null) | |
throw new ArgumentNullException(nameof(key)); | |
var dict = _attachmentTable.GetOrCreateValue(host); | |
object value; | |
var found = dict.TryGetValue(key, out value); | |
return new AttachmentResult<object>(found, value); | |
} | |
/// <summary> | |
/// Gets an attached value by key or by the the type parameter's | |
/// AssemblyQualifiedName. | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="host"></param> | |
/// <param name="key"></param> | |
/// <returns></returns> | |
public static AttachmentResult<T> GetAttached<T>(this object host, string key = null) | |
{ | |
key = key ?? typeof(T).AssemblyQualifiedName; | |
var dict = _attachmentTable.GetOrCreateValue(host); | |
object value; | |
var found = dict.TryGetValue(key, out value); | |
var castValue = found ? (T)value : default(T); | |
return new AttachmentResult<T>(found, castValue); | |
} | |
public static ICollection<string> GetAttachmentKeys(this object host) | |
{ | |
ConcurrentDictionary<string, object> dict; | |
if (_attachmentTable.TryGetValue(host, out dict)) | |
return dict.Keys; | |
return new string[0]; | |
} | |
/// <summary> | |
/// Removes every attached value from the host object. | |
/// </summary> | |
public static void ClearAttached(this object host) => _attachmentTable.Remove(host); | |
/// <summary> | |
/// Removes the specified attached value. | |
/// </summary> | |
public static AttachmentResult<object> RemoveAttached(this object host, string key) | |
{ | |
var dict = _attachmentTable.GetOrCreateValue(host); | |
object value; | |
var found = dict.TryRemove(key, out value); | |
return new AttachmentResult<object>(found, value); | |
} | |
/// <summary> | |
/// Removes the attached value. If a key isn't supplied | |
/// the type parameter's assembly qualified type name will be used. | |
/// </summary> | |
public static AttachmentResult<T> RemoveAttached<T>(this object host, string key = null) | |
{ | |
key = key ?? typeof(T).AssemblyQualifiedName; | |
var dict = _attachmentTable.GetOrCreateValue(host); | |
object value; | |
var found = dict.TryRemove(key, out value); | |
var castValue = found ? (T)value : default(T); | |
return new AttachmentResult<T>(found, castValue); | |
} | |
private static string RefIdKey = Guid.NewGuid().ToString(); | |
/// <summary> | |
/// Unique identifier for the object reference. | |
/// </summary> | |
public static Guid GetReferenceId(this object obj) => | |
obj.GetOrSetAttached(() => Guid.NewGuid(), RefIdKey).Value; | |
public class AttachmentResult<T> | |
{ | |
public bool Found { get; } | |
public T Value { get; } | |
public AttachmentResult(bool found, T value) | |
{ | |
Found = found; | |
Value = value; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment