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 BindingFlags Flags => BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; public static InitializationState State = InitializationState.None; private static Type[] types = Type.EmptyTypes; private static IEnumerable methods = new List(); private static IEnumerable fields = new List(); private static readonly Dictionary methodsCache = new(); private static readonly Dictionary fieldsCache = new(); private static readonly 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; } private static async Task EnsureConfig() { await TaskHelper.WaitUntil(() => State == InitializationState.Initialized); await UniTask.SwitchToThreadPool(); } internal static async UniTask Init() { if(State is InitializationState.Initializing) { await TaskHelper.WaitUntil(() => State is InitializationState.Initialized); return; } try { State = InitializationState.Initializing; await UniTask.SwitchToThreadPool(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); var loadedAssemblies = BITApp.Assemblies.IsValid() ? BITApp.Assemblies : GetAllAssemblies(); 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.CancellationToken.ThrowIfCancellationRequested(); } catch (System.Exception) { Reload(); return; } } var ignoreWatch = new Stopwatch(); var allTypesCount = result.Count; ignoreWatch.Start(); types = result .ToArray(); StringBuilder allNamespaceBuilder = new(); foreach (var x in types.Select(x => x.Namespace).Distinct()) { allNamespaceBuilder.AppendLine(x); } ignoreWatch.Stop(); 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 (Exception e) { BIT4Log.LogException(e); } State = InitializationState.Initialized; BIT4Log.Log("已完成初始化"); } private static Assembly[] GetAllAssemblies() { return AppDomain.CurrentDomain.GetAssemblies(); //return AppDomain.CurrentDomain.GetReferanceAssemblies().ToArray(); // var assemblies = new List(); // foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) // { // assemblies.Add(assembly); // foreach (var assemblyName in assembly.GetReferencedAssemblies()) // { // assemblies.Add(Assembly.Load(assemblyName)); // } // } // return assemblies.Distinct().ToArray(); } [ExcuteOnStop] public static void Reload() { State = InitializationState.None; types = Type.EmptyTypes; methods = Array.Empty(); fields = Array.Empty(); fieldsCache.Clear(); methodsCache.Clear(); } } public static class Extents { public static List GetReferanceAssemblies(this AppDomain domain) { var list = new List(); domain.GetAssemblies().ForEach(i => { GetReferanceAssemblies(i, list); }); return list; } static void GetReferanceAssemblies(Assembly assembly, List list) { assembly.GetReferencedAssemblies().ForEach(i => { try { var ass = Assembly.Load(i); if (!list.Contains(ass)) { list.Add(ass); GetReferanceAssemblies(ass, list); } } catch (Exception) { // ignored } }); } } }