diff --git a/Assets/Pacore/Runtime/ClassAttributeCache.cs b/Assets/Pacore/Runtime/ClassAttributeCache.cs index d12efd2..c1f7191 100644 --- a/Assets/Pacore/Runtime/ClassAttributeCache.cs +++ b/Assets/Pacore/Runtime/ClassAttributeCache.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Reflection; using System.Linq; using System; +using PashaBibko.Pacore.DevTools; using UnityEngine; namespace PashaBibko.Pacore @@ -13,53 +14,58 @@ namespace PashaBibko.Pacore public static ReadOnlyCollection GetAttributesOf() { - return AttributeCache.TryGetValue(typeof(T), out List classes) ? - classes.AsReadOnly() : - throw new ArgumentException($"Attribute [{nameof(T)}] is not used by any classes"); + return AttributeCache.TryGetValue(typeof(T), out List classes) + ? classes.AsReadOnly() + : throw new ArgumentException($"Attribute [{nameof(T)}] is not used by any classes"); } [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)] private static void ScanAllAssemblies() { - /* Fetches all the class types in all loaded assemblies */ - Type[] classes = AppDomain.CurrentDomain.GetAssemblies() // Assembly[] - .SelectMany(assembly => - { - try + using (CodeProfiler.Start("Assembly scan")) + { + /* Fetches all the class types in all loaded assemblies */ + Type[] classes = AppDomain.CurrentDomain.GetAssemblies() // Assembly[] + .SelectMany(assembly => { - return assembly.GetTypes(); + try + { + return assembly.GetTypes(); + } + + catch (ReflectionTypeLoadException err) + { + return err.Types.Where(t => t != null); + } + }) // IEnumerable + .Where(type => type.IsClass && !type.IsAbstract) // IEnumerable + .ToArray(); + + /* Allocates space for the cache */ + AttributeCache = classes // Type[] + .Where(type => typeof(Attribute).IsAssignableFrom(type)) // IEnumerable + .ToDictionary + ( + keySelector: t => t, + elementSelector: _ => new List() + ); // Dictionary> + + /* Finds which attributes are attached to what classes */ + HashSet seen = new(); + foreach (Type current in classes) + { + /* Tracks the seen attributes */ + seen.Clear(); + foreach (object attr in current.GetCustomAttributes(inherit: true)) + { + seen.Add(attr.GetType()); } - catch (ReflectionTypeLoadException err) + /* Adds the class type to each attribute in the dictionary */ + foreach (Type type in seen) { - return err.Types.Where(t => t != null); + AttributeCache[type].Add(current); } - }) // IEnumerable - .Where(type => type.IsClass && !type.IsAbstract) // IEnumerable - .ToArray(); - - /* Allocates space for the cache */ - AttributeCache = classes // Type[] - .Where(type => typeof(Attribute).IsAssignableFrom(type)) // IEnumerable - .ToDictionary - ( - keySelector: t => t, - elementSelector: _ => new List() - ); // Dictionary> - - /* Finds which attributes are attached to what classes */ - foreach (Type current in classes) - { - /* Finds all the attributes of the current class */ - Type[] attached = current // Type - .GetCustomAttributes(inherit: true) // object[] - .Select(attribute => attribute.GetType()) // IEnumerable - .Distinct().ToArray(); - - /* Adds the class type to each attribute in the dictionary */ - foreach (Type attribute in attached) - { - AttributeCache[attribute].Add(current); } } } diff --git a/Assets/TestMonoBehaviour.cs b/Assets/TestMonoBehaviour.cs index 4771ddb..afe07f1 100644 --- a/Assets/TestMonoBehaviour.cs +++ b/Assets/TestMonoBehaviour.cs @@ -14,20 +14,6 @@ using UnityEngine; private void OnTestChange() => LogTestValue(); - private void Update() - { - using (CodeProfiler.Start("Test Snippet")) - { - SpinWait sw = new(); - int count = Random.Range(1, 50); - - for (int i = 0; i < count; i++) - { - sw.SpinOnce(); - } - } - } - [InspectorCallable(nameof(LogSpawnableType))] public void LogSpawnableType() {