diff --git a/Assets/Pacore/Runtime/ClassAttributeCache.cs b/Assets/Pacore/Runtime/ClassAttributeCache.cs new file mode 100644 index 0000000..f6fc0df --- /dev/null +++ b/Assets/Pacore/Runtime/ClassAttributeCache.cs @@ -0,0 +1,67 @@ +using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.Reflection; +using System.Linq; +using System; +using UnityEngine; + +namespace PashaBibko.Pacore.Runtime +{ + public static class ClassAttributeCache + { + private static Dictionary> AttributeCache { get; set; } + + public static ReadOnlyCollection GetAttributesOf() + { + return AttributeCache.TryGetValue(typeof(T), out List attributes) ? + attributes.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 + { + 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 */ + 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); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Pacore/Runtime/ClassAttributeCache.cs.meta b/Assets/Pacore/Runtime/ClassAttributeCache.cs.meta new file mode 100644 index 0000000..98585ff --- /dev/null +++ b/Assets/Pacore/Runtime/ClassAttributeCache.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9e0be3076f094aa2a62c814ee0a75aee +timeCreated: 1769270329 \ No newline at end of file diff --git a/Assets/Pacore/Runtime/Pacore.asmdef b/Assets/Pacore/Runtime/Pacore.asmdef new file mode 100644 index 0000000..bea93ce --- /dev/null +++ b/Assets/Pacore/Runtime/Pacore.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Pacore", + "rootNamespace": "", + "references": [ + "GUID:73bc4dcce6d82e44c8fe9738b987d694" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Pacore/Runtime/Pacore.asmdef.meta b/Assets/Pacore/Runtime/Pacore.asmdef.meta new file mode 100644 index 0000000..758b36f --- /dev/null +++ b/Assets/Pacore/Runtime/Pacore.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 92a828b1c98146b48b5a7061ab1e8d2e +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: