using System; using System.Collections.Generic; using System.Reflection; using Cysharp.Threading.Tasks; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace BITKit { public class ReflectionHelper { public static InitializationState state = InitializationState.None; static Type[] types = new Type[0]; static IEnumerable methods = new List(); static IEnumerable fields = new List(); static Dictionary methodsCache = new(); static Dictionary fieldsCache = new(); static Dictionary attributes = new(); public static async Task> GetMethods() where Att : Attribute { await EnsureConfig(); var type = typeof(Att); if (methodsCache.TryGetValue(type, out var _methods)) { } else { _methods = methods.ToArray() .Where(x => x.GetCustomAttribute() is not null ).ToArray(); methodsCache.Add(type, _methods); } return _methods; } public static async Task> GetFields() where Att : Attribute { await EnsureConfig(); var type = typeof(Att); if (fieldsCache.TryGetValue(type, out var _fields)) { } else { _fields = fields .Where(x => x.GetCustomAttribute() is not null ).ToArray(); fieldsCache.Add(type, _fields); } return _fields; } public static async Task> GetTypes() { await EnsureConfig(); return types; } public static async Task> GetTypes() { var type = typeof(T); await EnsureConfig(); var currentTheadID = Thread.CurrentThread.ManagedThreadId.ToString(); BIT4Log.Log($"GetTypes运行于线程:{currentTheadID}"); return types .Where(x => x.IsAbstract is false) .Where(x => type.IsAssignableFrom(x)); } public static async Task> GetAttributes() where Att : Attribute { await EnsureConfig(); List atts = new(); var _atts = types .Where(x => x.IsAbstract is false) .Where(x => x.GetCustomAttribute() is not null) .Select(x => x.GetCustomAttribute()); foreach (var att in _atts) { if (att is not null) { atts.Add(att); } } return atts; } public static async Task> GetInstances() where T : class { await EnsureConfig(); var results = new List(); var instances = (await GetTypes()) .Where(x => x.IsClass) .Where(x => x.IsAbstract is false) #if UNITY //.Where(x=>x.IsAssignableFrom(typeof(UnityEngine.Object))is false) .Where(x=>typeof(UnityEngine.Object).IsAssignableFrom(x) is false) #endif .Where(x => x.ContainsGenericParameters is false) .Select(x => { try { var instance = System.Activator.CreateInstance(x) as T; DI.Inject(instance); return instance; } catch (Exception e) { BIT4Log.LogException(e); } return null; }); foreach (var instance in instances) { if (instance is not null) { results.Add(instance); } } return results; } static async Task EnsureConfig() { await TaskHelper.WaitUntil(() => state == InitializationState.Initialized); await UniTask.SwitchToThreadPool(); } internal static void Init() { try { state = InitializationState.Initializing; lock (types) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); var loadedAssemblies = BITApp.Assemblies.IsValid() ? BITApp.Assemblies : AppDomain.CurrentDomain.GetAssemblies(); BIT4Log.Log($"已加载程序集:{loadedAssemblies.Length}个"); var result = new List(); for (var i = 0; i < loadedAssemblies.Length; i++) { var asm = loadedAssemblies[i]; try { foreach (var x in asm.GetExportedTypes()) { var rootNamespace = x.Namespace; if(string.IsNullOrEmpty(rootNamespace)) { rootNamespace = Constant.System.Internal; } else { rootNamespace = rootNamespace.Split(@".").First(); } if(BITApp.Settings.whiteList.Count > 0) { if(BITApp.Settings.whiteList.Contains(rootNamespace)) { result.Add(x); } } else { if(BITApp.Settings.blackList.Contains(rootNamespace) is false) { result.Add(x); } } } } catch { continue; } try { BITApp.CancellationTokenSource.Token.ThrowIfCancellationRequested(); } catch (System.Exception) { Reload(); return; } } Stopwatch ignoreWatch = new Stopwatch(); var allTypesCount = result.Count; ignoreWatch.Start(); types = result .ToArray(); ignoreWatch.Stop(); StringBuilder allNamespaceBuilder = new(); foreach (var x in types.Select(x => x.Namespace).Distinct()) { allNamespaceBuilder.AppendLine(x); } BIT4Log.Log($"已加载的命名空间:\n{allNamespaceBuilder}"); BIT4Log.Log($"忽略部分Types:{ignoreWatch.ElapsedMilliseconds}ms"); methods = types.SelectMany(x => x.GetMethods()); fields = types.SelectMany(x => x.GetFields()); stopWatch.Stop(); BIT4Log.Log($"获取所有Types:{stopWatch.ElapsedMilliseconds}ms"); } } catch (System.Exception e) { BIT4Log.LogException(e); } state = InitializationState.Initialized; BIT4Log.Log("已完成初始化"); } [ExcuteOnStop] public static void Reload() { state = InitializationState.None; types = new Type[0]; methods = new MethodInfo[0]; fields = new FieldInfo[0]; fieldsCache.Clear(); methodsCache.Clear(); } } }