Implement type dictionaries, with hierarchical sets and unsets.
This commit is contained in:
parent
1dcf167022
commit
c538dbd56b
157
Dashboard.Common/Collections/TypeDictionary.cs
Normal file
157
Dashboard.Common/Collections/TypeDictionary.cs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Dashboard.Collections
|
||||||
|
{
|
||||||
|
public class TypeDictionary<T>(bool hierarchical = false) : IEnumerable<T>
|
||||||
|
{
|
||||||
|
private readonly Dictionary<int, T> _objects = new Dictionary<int, T>();
|
||||||
|
|
||||||
|
public bool Contains<T2>() where T2 : T => _objects.ContainsKey(TypeAtom<T2>.Id);
|
||||||
|
|
||||||
|
public bool Add<T2>(T2 value) where T2 : T
|
||||||
|
{
|
||||||
|
TypeAtom atom = TypeAtom<T2>.Atom;
|
||||||
|
|
||||||
|
if (!_objects.TryAdd(atom.Id, value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!hierarchical)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (TypeAtom ancestor in atom.Ancestors)
|
||||||
|
{
|
||||||
|
_objects[ancestor.Id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T2 Get<T2>() where T2 : T => TryGet(out T2? value) ? value : throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
public void Set<T2>(T2 value) where T2 : T
|
||||||
|
{
|
||||||
|
TypeAtom atom = TypeAtom<T2>.Atom;
|
||||||
|
_objects[atom.Id] = value;
|
||||||
|
|
||||||
|
if (!hierarchical)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (TypeAtom ancestor in atom.Ancestors)
|
||||||
|
{
|
||||||
|
_objects[ancestor.Id] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove<T2>() where T2 : T => Remove<T>(out _);
|
||||||
|
|
||||||
|
public bool Remove<T2>([NotNullWhen(true)] out T2? value) where T2 : T
|
||||||
|
{
|
||||||
|
TypeAtom atom = TypeAtom<T2>.Atom;
|
||||||
|
|
||||||
|
if (!_objects.Remove(atom.Id, out T? subValue))
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (T2?)subValue;
|
||||||
|
|
||||||
|
if (hierarchical)
|
||||||
|
{
|
||||||
|
foreach (TypeAtom ancestor in atom.Ancestors)
|
||||||
|
{
|
||||||
|
_objects.Remove(ancestor.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGet<T2>([NotNullWhen(true)] out T2? value) where T2 : T
|
||||||
|
{
|
||||||
|
if (!_objects.TryGetValue(TypeAtom<T2>.Id, out T? subValue))
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (T2?)subValue;
|
||||||
|
return value != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear() => _objects.Clear();
|
||||||
|
|
||||||
|
public IEnumerator<T> GetEnumerator() => _objects.Values.GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TypeDictionary<TKey, TValue>(bool hierarchical = false) : IEnumerable<KeyValuePair<TypeAtom, TValue>>
|
||||||
|
{
|
||||||
|
private readonly Dictionary<int, TValue> _objects = new Dictionary<int, TValue>();
|
||||||
|
|
||||||
|
public bool Contains<TKey2>() where TKey2 : TKey => _objects.ContainsKey(TypeAtom<TKey2>.Id);
|
||||||
|
|
||||||
|
public bool Add<TKey2>(TValue value) where TKey2 : TKey
|
||||||
|
{
|
||||||
|
TypeAtom atom = TypeAtom<TKey2>.Atom;
|
||||||
|
|
||||||
|
if (!_objects.TryAdd(atom.Id, value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!hierarchical)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (TypeAtom ancestor in atom.Ancestors)
|
||||||
|
{
|
||||||
|
_objects[ancestor.Id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TValue Get<TKey2>() where TKey2 : TKey => (TValue)_objects[TypeAtom<TKey2>.Id]!;
|
||||||
|
|
||||||
|
public void Set<TKey2>(TValue value) where TKey2 : TKey
|
||||||
|
{
|
||||||
|
TypeAtom atom = TypeAtom<TKey2>.Atom;
|
||||||
|
_objects[atom.Id] = value;
|
||||||
|
|
||||||
|
if (!hierarchical)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (TypeAtom ancestor in atom.Ancestors)
|
||||||
|
{
|
||||||
|
_objects[ancestor.Id] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove<TKey2>() where TKey2 : TKey => Remove<TKey2>(out _);
|
||||||
|
public bool Remove<TKey2>([MaybeNullWhen(false)] out TValue? value) where TKey2 : TKey
|
||||||
|
{
|
||||||
|
TypeAtom atom = TypeAtom<TKey2>.Atom;
|
||||||
|
|
||||||
|
if (!_objects.Remove(atom.Id, out value))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hierarchical)
|
||||||
|
{
|
||||||
|
foreach (TypeAtom ancestor in atom.Ancestors)
|
||||||
|
{
|
||||||
|
_objects.Remove(ancestor.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGet<TKey2>([NotNullWhen(true)] out TValue? value) where TKey2 : TKey => _objects.TryGetValue(TypeAtom<TKey2>.Id, out value);
|
||||||
|
|
||||||
|
public void Clear() => _objects.Clear();
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<TypeAtom, TValue>> GetEnumerator() => _objects.Select(x => new KeyValuePair<TypeAtom, TValue>(TypeAtom.Get(x.Key)!, x.Value)).GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user