1
This commit is contained in:
122
Packages/Core/Utils/Data.cs
Normal file
122
Packages/Core/Utils/Data.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Linq;
|
||||
|
||||
namespace BITKit
|
||||
{
|
||||
public static class Data
|
||||
{
|
||||
[ExcuteOnStop]
|
||||
public static void Reload()
|
||||
{
|
||||
dictionary.Clear();
|
||||
events.Clear();
|
||||
}
|
||||
public static readonly Dictionary<string, object> Objects = new();
|
||||
public static readonly ConcurrentDictionary<string, List<object>> rawEvents = new();
|
||||
static readonly ConcurrentDictionary<string, object> dictionary = new();
|
||||
static readonly ConcurrentDictionary<string, List<object>> events = new();
|
||||
public static void AddListener<T>(Action<T> action, bool autoInvoke = false) =>
|
||||
AddListener<T>(Constant.System.Internal, action, autoInvoke);
|
||||
public static void RemoveListender<T>(Action<T> action) =>
|
||||
RemoveListender<T>(Constant.System.Internal, action);
|
||||
public static void Set<T>(T value) =>
|
||||
Set<T>(Constant.System.Internal, value);
|
||||
public static void AddListener<T>(string key, Action<T> action, bool autoInvoke = false)
|
||||
{
|
||||
rawEvents.AddOrUpdate(key, x => new List<object>() { action }, (x, y) =>
|
||||
{
|
||||
y.Add(action);
|
||||
return y;
|
||||
});
|
||||
key = Generic<T>.GetVariable(key);
|
||||
events.Get(key).Add(action);
|
||||
if (autoInvoke)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
if (value is T t)
|
||||
{
|
||||
action.Invoke(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void RemoveListender<T>(string key, Action<T> action)
|
||||
{
|
||||
var list = rawEvents.GetOrAdd(key, x => new());
|
||||
list.TryRemove(action);
|
||||
key = Generic<T>.GetVariable(key);
|
||||
events.Get(key).Remove(action);
|
||||
}
|
||||
public static void Set<T>(string key, T value)
|
||||
{
|
||||
key = Generic<T>.GetVariable(key);
|
||||
if (dictionary.ContainsKey(key))
|
||||
{
|
||||
dictionary.AddOrUpdate(key, (x) => value, (x, y) => value);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.GetOrAdd(key, value);
|
||||
}
|
||||
|
||||
var list = events.Get(key);
|
||||
list.ToArray().ForEach(x =>
|
||||
{
|
||||
var action = x as Action<T>;
|
||||
action.Invoke(value);
|
||||
});
|
||||
if (value is not JToken)
|
||||
Objects.TryInsert(key, value);
|
||||
|
||||
}
|
||||
public static bool TryGetValue<T>(string key, out T value)
|
||||
{
|
||||
key = Generic<T>.GetVariable(key);
|
||||
if (dictionary.TryGetValue(key, out var _value))
|
||||
{
|
||||
if (_value is T t)
|
||||
{
|
||||
value = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
public static T Get<T>(string key = Constant.System.Internal)
|
||||
{
|
||||
key = Generic<T>.GetVariable(key);
|
||||
if (dictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
if (value is T t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return default;
|
||||
}
|
||||
public static void Clear()
|
||||
{
|
||||
dictionary.Clear();
|
||||
}
|
||||
public static void Clear<T>()
|
||||
{
|
||||
ConcurrentDictionary<string, object> copy = new(dictionary);
|
||||
object output;
|
||||
foreach (var item in copy)
|
||||
{
|
||||
if (item.Value is T)
|
||||
{
|
||||
dictionary.Remove(item.Key, out output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
11
Packages/Core/Utils/Data.cs.meta
Normal file
11
Packages/Core/Utils/Data.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1554f5997819ee144a963276ddc39370
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
152
Packages/Core/Utils/DataParser.cs
Normal file
152
Packages/Core/Utils/DataParser.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
namespace BITKit
|
||||
{
|
||||
public static class DataParser
|
||||
{
|
||||
public static readonly Action<string> OnSet = Set;
|
||||
[BITCommand]
|
||||
public static void Get(string key)
|
||||
{
|
||||
BIT4Log.Log(Data.Get<string>(key));
|
||||
}
|
||||
[BITCommand]
|
||||
public static void Set(string key, string value)
|
||||
{
|
||||
Data.Set(key, value);
|
||||
if (Guid.TryParse(value, out var guidResult))
|
||||
{
|
||||
Data.Set(key, guidResult);
|
||||
}
|
||||
else if (bool.TryParse(value, out var boolResult))
|
||||
{
|
||||
Data.Set(key, boolResult);
|
||||
}
|
||||
else if (float.TryParse(value, out var floatResult))
|
||||
{
|
||||
Data.Set(key, floatResult);
|
||||
}
|
||||
else if (int.TryParse(value, out var intResult))
|
||||
{
|
||||
Data.Set(key, intResult);
|
||||
}
|
||||
}
|
||||
[BITCommand]
|
||||
public static void SetContainer(string key, string typeName, string json)
|
||||
{
|
||||
try
|
||||
{
|
||||
var type = Type.GetType(typeName, true);
|
||||
var value = JsonConvert.DeserializeObject(json, type);
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
throw;
|
||||
//Debug.LogException(e);
|
||||
}
|
||||
|
||||
}
|
||||
[BITCommand]
|
||||
public static async void ShowAllData()
|
||||
{
|
||||
await UniTask.SwitchToThreadPool();
|
||||
StringBuilder stringBuilder = new();
|
||||
lock (Data.Objects)
|
||||
{
|
||||
Dictionary<string, object> copy = new(Data.Objects);
|
||||
foreach (var item in copy)
|
||||
{
|
||||
stringBuilder.AppendLine($"{item.Key}:{item.Value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void Set(string json)
|
||||
{
|
||||
if (string.IsNullOrEmpty(json) is false)
|
||||
{
|
||||
try
|
||||
{
|
||||
ForEach(JObject.Parse(json));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void ForEach(JToken jToken)
|
||||
{
|
||||
var path = jToken.Path;
|
||||
switch (jToken.Type)
|
||||
{
|
||||
case JTokenType.Array:
|
||||
Data.Set(path, jToken.ToObject<JArray>());
|
||||
break;
|
||||
case JTokenType.Boolean:
|
||||
Data.Set(path, jToken.ToObject<bool>());
|
||||
goto case JTokenType.String;
|
||||
case JTokenType.Bytes:
|
||||
Data.Set(path, jToken.ToObject<byte[]>());
|
||||
break;
|
||||
case JTokenType.Date:
|
||||
Data.Set(path, jToken.ToObject<DateTime>());
|
||||
goto case JTokenType.String;
|
||||
case JTokenType.Float:
|
||||
Data.Set(path, jToken.ToObject<float>());
|
||||
goto case JTokenType.String;
|
||||
case JTokenType.Guid:
|
||||
Data.Set(path, jToken.ToObject<Guid>());
|
||||
goto case JTokenType.String;
|
||||
case JTokenType.Integer:
|
||||
Data.Set(path, jToken.ToObject<int>());
|
||||
goto case JTokenType.String;
|
||||
case JTokenType.String:
|
||||
Data.Set(path, jToken.ToObject<string>());
|
||||
break;
|
||||
case JTokenType.TimeSpan:
|
||||
Data.Set(path, jToken.ToObject<TimeSpan>());
|
||||
goto case JTokenType.String;
|
||||
case JTokenType.Property:
|
||||
Data.Set(path, jToken.ToObject<JProperty>());
|
||||
/*
|
||||
var list = Data.rawEvents.GetOrAdd(path,x=> new());
|
||||
foreach (var item in list)
|
||||
{
|
||||
var type = item.GetType();
|
||||
var genericType = item.GetType().GetGenericArguments().First();
|
||||
try
|
||||
{
|
||||
var value = jToken.ToObject(genericType);
|
||||
var method = type.GetMethod(nameof(Action.Invoke));
|
||||
method.Invoke(value, new object[] { value });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.AppendLine($"<22>ѻ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:{genericType}");
|
||||
stringBuilder.AppendLine($"<22>ѻ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:{type}");
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
}
|
||||
Data.Set(path, jToken.ToObject<JProperty>());
|
||||
*/
|
||||
break;
|
||||
case JTokenType.Object:
|
||||
Data.Set(path, jToken.ToObject<JObject>());
|
||||
break;
|
||||
}
|
||||
foreach (var j in jToken)
|
||||
{
|
||||
ForEach(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Packages/Core/Utils/DataParser.cs.meta
Normal file
11
Packages/Core/Utils/DataParser.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 848023505fe498c47a93ee46e9c32342
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
58
Packages/Core/Utils/PathHelper.cs
Normal file
58
Packages/Core/Utils/PathHelper.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
namespace BITKit
|
||||
{
|
||||
public class PathHelper
|
||||
{
|
||||
static string appDataPath=_appDataPath;
|
||||
[ExcuteOnAwake]
|
||||
public static void Init()
|
||||
{
|
||||
if (string.IsNullOrEmpty(appDataPath))
|
||||
{
|
||||
appDataPath = Path.Combine(Environment.CurrentDirectory, BITApp.AppName);
|
||||
}
|
||||
BIT4Log.Log<PathHelper>($"配置文件路径:{appDataPath}");
|
||||
DirectoryInfo directoryInfo = new(appDataPath);
|
||||
directoryInfo.Create();
|
||||
}
|
||||
public static string GetFolderPath(params string[] paths)
|
||||
{
|
||||
var path = GetPath(paths);
|
||||
if (path is not null)
|
||||
{
|
||||
DirectoryInfo directoryInfo = new(path);
|
||||
directoryInfo.Create();
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
return GetPath(paths);
|
||||
}
|
||||
public static string GetFilePath(params string[] paths)
|
||||
{
|
||||
var path = GetPath(paths);
|
||||
var dictionaryPath = Path.GetDirectoryName(path);
|
||||
Directory.CreateDirectory(dictionaryPath);
|
||||
if (File.Exists(path) is false)
|
||||
{
|
||||
using (var fs = File.Create(path))
|
||||
{
|
||||
fs.Close();
|
||||
fs.Dispose();
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
public static string GetTempFilePath(string fileName = null)
|
||||
{
|
||||
var path = GetFilePath("Temps", fileName is null ? Guid.NewGuid().ToString():fileName);
|
||||
return path;
|
||||
}
|
||||
public static string GetPath(params string[] paths)
|
||||
{
|
||||
return Path.Combine(appDataPath, Path.Combine(paths));
|
||||
}
|
||||
static string _appDataPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
BITApp.AppName);
|
||||
}
|
||||
}
|
11
Packages/Core/Utils/PathHelper.cs.meta
Normal file
11
Packages/Core/Utils/PathHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2d83241c4e1cc04da163f221bb6e325
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
228
Packages/Core/Utils/ReflectionHelper.cs
Normal file
228
Packages/Core/Utils/ReflectionHelper.cs
Normal file
@@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
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
|
||||
{
|
||||
|
||||
BIT4Log.Log<ReflectionHelper>("正在初始化");
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
11
Packages/Core/Utils/ReflectionHelper.cs.meta
Normal file
11
Packages/Core/Utils/ReflectionHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6366742b2b205741b86e1203465a5b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user