Skip to content

Instantly share code, notes, and snippets.

@Arlodotexe
Last active March 29, 2020 10:36
Show Gist options
  • Save Arlodotexe/0527522ff54ca3839bf51c61c89cce83 to your computer and use it in GitHub Desktop.
Save Arlodotexe/0527522ff54ca3839bf51c61c89cce83 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AppName
{
public class InstanceContainer
{
public InstanceContainer(WeakReference<object> instance)
{
Instance = instance;
}
public InstanceContainer(WeakReference<object> instance, string contextIdentifier, bool isPrimary)
{
Instance = instance;
ContextIdentifier = contextIdentifier;
IsPrimary = isPrimary;
}
public InstanceContainer(WeakReference<object> instance, bool isPrimary)
{
Instance = instance;
IsPrimary = isPrimary;
}
public WeakReference<object> Instance;
/// <summary>
/// Identifies an instance based on a declared context
/// </summary>
public string ContextIdentifier;
/// <summary>
/// Prefferred instance of an object
/// </summary>
public bool IsPrimary;
}
public static class InstanceLocator
{
public static List<InstanceContainer> Instances { get; set; } = new List<InstanceContainer>();
public static IEnumerable<T> GetAll<T>()
{
return Instances.Where(i => i.Instance.TryGetTarget(out object data) && data is T)?.Select(i =>
{
i.Instance.TryGetTarget(out object returnVal);
return (T)returnVal;
});
}
public static void ExecAll<T>(Action<T> action)
{
foreach (var reference in Instances.Where(i => i.Instance.TryGetTarget(out object data) && data is T))
{
reference.Instance.TryGetTarget(out object output);
action((T)output);
}
}
public static async Task ExecAllAsync<T>(Func<T, Task> action)
{
foreach (var reference in Instances.Where(i => i.Instance.TryGetTarget(out object data) && data is T))
{
reference.Instance.TryGetTarget(out object output);
await action((T)output);
}
}
public static T GetByContext<T>(object contextIdentifier)
{
object returnVal = null;
foreach (var reference in Instances.Where(i => i.Instance.TryGetTarget(out object data) && data is T))
{
if (reference.ContextIdentifier == contextIdentifier.ToString())
{
reference.Instance.TryGetTarget(out returnVal);
break;
}
}
return (T)returnVal;
}
public static T GetPrimary<T>()
{
object returnVal = null;
foreach (var reference in Instances.Where(i => i.Instance.TryGetTarget(out object data) && data is T))
{
if (reference.IsPrimary)
{
reference.Instance.TryGetTarget(out returnVal);
break;
}
}
return (T)returnVal;
}
public static void Add<T>(T instance, bool isPrimary = false)
{
Instances.Add(new InstanceContainer(new WeakReference<object>(instance), isPrimary));
}
public static void Add<T>(T instance, object contextIdentifier, bool isPrimary = false)
{
if (Instances.Any(i => i.ContextIdentifier == contextIdentifier.ToString()))
throw new InvalidOperationException($"Identifier \"{contextIdentifier}\" already exists");
Instances.Add(new InstanceContainer(new WeakReference<object>(instance), contextIdentifier.ToString(), isPrimary));
}
public static void Remove<T>(object contextIdentifier)
{
Instances.Remove(Instances.FirstOrDefault(i => i.Instance.TryGetTarget(out object data) && data is T && i.ContextIdentifier == contextIdentifier.ToString()));
}
public static void RemoveAll<T>()
{
Instances.RemoveAll(i => i.Instance.TryGetTarget(out object data) && data is T);
}
public static void SelectPrimary(object contextIdentifier)
{
foreach (var instanceContainer in Instances)
{
// Sets to true if the context identifier matches, sets to false if not
instanceContainer.IsPrimary =
instanceContainer.ContextIdentifier == contextIdentifier.ToString();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment