BITKit/Packages/Runtime~/Core/Utils/ReflectionHelper.cs

224 lines
8.3 KiB
C#

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<MethodInfo> methods = new List<MethodInfo>();
static IEnumerable<FieldInfo> fields = new List<FieldInfo>();
static Dictionary<Type, MethodInfo[]> methodsCache = new();
static Dictionary<Type, FieldInfo[]> fieldsCache = new();
static Dictionary<Attribute, Attribute[]> attributes = new();
public static async Task<IEnumerable<MethodInfo>> GetMethods<Att>() where Att : Attribute
{
await EnsureConfig();
var type = typeof(Att);
if (methodsCache.TryGetValue(type, out var _methods))
{
}
else
{
_methods = methods.ToArray()
.Where(x => x.GetCustomAttribute<Att>() is not null
).ToArray();
methodsCache.Add(type, _methods);
}
return _methods;
}
public static async Task<IEnumerable<FieldInfo>> GetFields<Att>() where Att : Attribute
{
await EnsureConfig();
var type = typeof(Att);
if (fieldsCache.TryGetValue(type, out var _fields))
{
}
else
{
_fields = fields
.Where(x => x.GetCustomAttribute<Att>() is not null
).ToArray();
fieldsCache.Add(type, _fields);
}
return _fields;
}
public static async Task<IEnumerable<Type>> GetTypes()
{
await EnsureConfig();
return types;
}
public static async Task<IEnumerable<Type>> GetTypes<T>()
{
var type = typeof(T);
await EnsureConfig();
var currentTheadID = Thread.CurrentThread.ManagedThreadId.ToString();
BIT4Log.Log<ReflectionHelper>($"GetTypes运行于线程:{currentTheadID}");
return types
.Where(x => x.IsAbstract is false)
.Where(x => type.IsAssignableFrom(x));
}
public static async Task<IEnumerable<Att>> GetAttributes<Att>() where Att : Attribute
{
await EnsureConfig();
List<Att> atts = new();
var _atts = types
.Where(x => x.IsAbstract is false)
.Where(x => x.GetCustomAttribute<Att>() is not null)
.Select(x => x.GetCustomAttribute<Att>());
foreach (var att in _atts)
{
if (att is not null)
{
atts.Add(att);
}
}
return atts;
}
public static async Task<IEnumerable<T>> GetInstances<T>() where T : class
{
await EnsureConfig();
var results = new List<T>();
var instances = (await GetTypes<T>())
.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<ReflectionHelper>($"已加载程序集:{loadedAssemblies.Length}个");
var result = new List<Type>();
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<ReflectionHelper>($"已加载的命名空间:\n{allNamespaceBuilder}");
BIT4Log.Log<ReflectionHelper>($"忽略部分Types:{ignoreWatch.ElapsedMilliseconds}ms");
methods = types.SelectMany(x => x.GetMethods());
fields = types.SelectMany(x => x.GetFields());
stopWatch.Stop();
BIT4Log.Log<ReflectionHelper>($"获取所有Types:{stopWatch.ElapsedMilliseconds}ms");
}
}
catch (System.Exception e)
{
BIT4Log.LogException(e);
}
state = InitializationState.Initialized;
BIT4Log.Log<ReflectionHelper>("已完成初始化");
}
[ExcuteOnStop]
public static void Reload()
{
state = InitializationState.None;
types = new Type[0];
methods = new MethodInfo[0];
fields = new FieldInfo[0];
fieldsCache.Clear();
methodsCache.Clear();
}
}
}