diff --git a/Dashboard.Common/Collections/TypeAtom.cs b/Dashboard.Common/Collections/TypeAtom.cs
new file mode 100644
index 0000000..446b792
--- /dev/null
+++ b/Dashboard.Common/Collections/TypeAtom.cs
@@ -0,0 +1,95 @@
+using System.Collections.Concurrent;
+using System.Collections.Immutable;
+
+namespace Dashboard.Collections
+{
+ ///
+ /// Helper class for better type access performance.
+ ///
+ public record TypeAtom
+ {
+
+ public Type Type { get; }
+ public int Id { get; }
+ public ImmutableHashSet Ancestors { get; }
+
+ // Makes it so TypeAtom doesn't get pissed at me
+ private protected TypeAtom()
+ {
+ throw new NotSupportedException();
+ }
+
+ private TypeAtom(Type type)
+ {
+ Type = type;
+
+ HashSet ancestors = new HashSet();
+ FindAncestors(Type, ancestors);
+ ancestors.Add(this);
+ Ancestors = ancestors.ToImmutableHashSet();
+
+ lock (s_lockObject)
+ {
+ Id = s_counter++;
+ s_atoms.Add(Id, this);
+ s_types.Add(Type, this);
+ }
+ }
+
+ private static readonly object s_lockObject = new object();
+ private static readonly Dictionary s_atoms = new Dictionary();
+ private static readonly Dictionary s_types = new Dictionary();
+
+ private static int s_counter = 0;
+
+ public static TypeAtom? Get(int id) => s_atoms.GetValueOrDefault(id);
+ public static TypeAtom Get(Type type)
+ {
+ if (s_types.TryGetValue(type, out TypeAtom? id))
+ return id;
+
+ // Type is not registered, try to acquire lock.
+ lock (s_lockObject)
+ {
+ // Maybe somebody else registered this type whilst acquiring the lock.
+ if (s_types.TryGetValue(type, out id))
+ return id;
+
+ // Register the type if applicable and leave.
+ return new TypeAtom(type);
+ }
+
+ }
+
+ private static void FindAncestors(Type type, HashSet destination)
+ {
+ // Traverse the object tree for all possible aliases.
+ if (type.BaseType != null)
+ {
+ foreach (TypeAtom ancestor in Get(type.BaseType).Ancestors)
+ {
+ destination.Add(ancestor);
+ }
+ }
+
+ foreach (Type trait in type.GetInterfaces())
+ {
+ TypeAtom atom = Get(trait);
+ destination.Add(atom);
+ }
+ }
+ }
+
+ ///
+ /// Helper class for better type access performance.
+ ///
+ public sealed record TypeAtom : TypeAtom
+ {
+ public static TypeAtom Atom { get; } = Get(typeof(T));
+ public new static int Id => Atom.Id;
+ public new static Type Type => Atom.Type;
+ public new static ImmutableHashSet Ancestors => Atom.Ancestors;
+
+ private TypeAtom() { }
+ }
+}
diff --git a/Dashboard.Common/Collections/TypeHashSet.cs b/Dashboard.Common/Collections/TypeHashSet.cs
new file mode 100644
index 0000000..3761509
--- /dev/null
+++ b/Dashboard.Common/Collections/TypeHashSet.cs
@@ -0,0 +1,44 @@
+using System.Collections;
+
+namespace Dashboard.Collections
+{
+ public class TypeHashSet(bool hierarchical = false) : IEnumerable
+ {
+ private readonly HashSet _set = new HashSet();
+
+ public bool Contains() => _set.Contains(TypeAtom.Id);
+
+ public bool Set()
+ {
+ if (!_set.Add(TypeAtom.Id))
+ return false;
+
+ if (hierarchical)
+ foreach (TypeAtom ancestor in TypeAtom.Ancestors)
+ {
+ _set.Add(ancestor.Id);
+ }
+
+ return true;
+ }
+
+ public bool Reset()
+ {
+ if (!_set.Remove(TypeAtom.Id))
+ return false;
+
+ if (hierarchical)
+ foreach (TypeAtom ancestor in TypeAtom.Ancestors)
+ {
+ _set.Remove(ancestor.Id);
+ }
+
+ return true;
+ }
+
+ public void Clear() => _set.Clear();
+
+ public IEnumerator GetEnumerator() => _set.Select(x => TypeAtom.Get(x)!).GetEnumerator();
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+}