142 lines
3.7 KiB
C#
142 lines
3.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.Cryptography;
|
|
using BITKit.UX;
|
|
using Newtonsoft.Json;
|
|
using Unity.Collections;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
|
|
namespace BITKit.IData
|
|
{
|
|
public class UXDataBindingService : MonoBehaviour
|
|
{
|
|
[RuntimeInitializeOnLoadMethod]
|
|
private static void Reload()
|
|
{
|
|
_Binders.Clear();
|
|
_Instances.Clear();
|
|
}
|
|
private static readonly Dictionary<Type,IUXDataBinder> _Binders = new();
|
|
private static readonly CacheList<IUXDataBinder> _Instances = new();
|
|
|
|
public static VisualElement Create(object target)
|
|
{
|
|
var visualElement = new VisualElement();
|
|
var fields = target.GetType().GetFields(ReflectionHelper.Flags);
|
|
foreach (var fieldInfo in fields.Where(x=>x.GetCustomAttribute<ExportAttribute>() is not null))
|
|
{
|
|
var handler = UXDataBindingService.Create(target,fieldInfo);
|
|
var ui = handler.CreateUI(target, fieldInfo);
|
|
visualElement.Add(ui);
|
|
}
|
|
|
|
foreach (var methodInfo in target.GetType().GetMethods(ReflectionHelper.Flags))
|
|
{
|
|
if (Attribute.IsDefined(methodInfo, typeof(ExportAttribute)) is false) continue;
|
|
var exportAttribute = methodInfo.GetCustomAttribute<ExportAttribute>();
|
|
|
|
var button = visualElement.Create<Button>();
|
|
button.text =string.IsNullOrEmpty(exportAttribute.Name) ? methodInfo.Name:exportAttribute.Name;
|
|
|
|
button.clicked += OnClicked;
|
|
|
|
continue;
|
|
void OnClicked()
|
|
{
|
|
try
|
|
{
|
|
methodInfo.Invoke(target, null);
|
|
}
|
|
catch (TargetInvocationException targetInvocationException)
|
|
{
|
|
if (targetInvocationException.InnerException is InGameException e is false) return;
|
|
switch (e)
|
|
{
|
|
case {InnerException:not null}:
|
|
Alert.Print(e.Message,e.InnerException.Message);
|
|
break;
|
|
default:
|
|
Alert.Print(e.Message,e.Source);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return visualElement;
|
|
}
|
|
|
|
public static IUXDataBinder Create(object target,FieldInfo fieldInfo)
|
|
{
|
|
var value = fieldInfo.GetValue(target);
|
|
var type = value?.GetType() ?? fieldInfo.FieldType;
|
|
|
|
// if (value is IEnumerable)
|
|
// {
|
|
// //type = typeof(IEnumerable<>).MakeGenericType(fieldInfo.FieldType.GetElementType());
|
|
// //type = typeof(IEnumerable<>).MakeGenericType(type.GetGenericArguments());
|
|
// }
|
|
|
|
switch (value)
|
|
{
|
|
case Array:
|
|
type = typeof(IEnumerable<>).MakeGenericType(fieldInfo.FieldType.GetElementType());
|
|
break;
|
|
case IList:
|
|
type = typeof(IEnumerable<>).MakeGenericType(type.GetGenericArguments());
|
|
break;
|
|
}
|
|
|
|
if (_Binders.TryGetValue(type, out var binder) is false)
|
|
throw new NotImplementedException($"未支持的类型:{type.Name}");
|
|
|
|
var instance = (IUXDataBinder)Activator.CreateInstance(binder.GetType());
|
|
_Instances.Add(instance);
|
|
|
|
return instance;
|
|
}
|
|
|
|
[SerializeReference, SubclassSelector] private ITicker ticker;
|
|
|
|
private async void Start()
|
|
{
|
|
var binders = await ReflectionHelper.GetTypes<IUXDataBinder>();
|
|
if(destroyCancellationToken.IsCancellationRequested)return;
|
|
|
|
foreach (var x in binders)
|
|
{
|
|
var instance = (IUXDataBinder)Activator.CreateInstance(x);
|
|
if (_Binders.TryAdd(instance.TargetType, instance)) ;
|
|
}
|
|
|
|
ticker.Add(OnTick);
|
|
|
|
destroyCancellationToken.Register(() =>
|
|
{
|
|
ticker.Remove(OnTick);
|
|
});
|
|
}
|
|
private static void OnTick(float obj)
|
|
{
|
|
var array = _Instances.ValueArray;
|
|
foreach (var x in array)
|
|
{
|
|
if (x.VisualElement.panel is null)
|
|
{
|
|
_Instances.Remove(x);
|
|
continue;
|
|
}
|
|
x.OnTick(obj);
|
|
}
|
|
}
|
|
}
|
|
}
|