using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using TinaX.Core.Localization; using TinaX.UIKit.Components; using TinaX.UIKit.DataBinding; using TinaX.UIKit.MVVM.BindingConverter; using TinaX.UIKit.MVVM.Components; using TinaX.UIKit.MVVM.Interfaces; using TinaX.UIKit.MVVM.Services; using TinaX.XComponent; using UnityEngine; namespace TinaX.UIKit.MVVM.Pipeline { public class XComponentViewModeHandler : IViewModelHandler { public IViewModelHandler Handler => this; public bool HandleViewModel(BinderHandlerBaseComponent handlerComponent, IUIKitMvvmService mvvmService) { var xcomponent = handlerComponent.gameObject.GetComponent(); if(xcomponent == null) { return false; //当前handler不处理该UI } var xbehaviour = xcomponent.Behaviour; //获取所有Binder组件 var binders = handlerComponent.gameObject.GetComponentsInChildren(); //Debug.Log("获取到Binder组件数:" + binders.Length); //反射出所有绑定数据 Dictionary _dict_BindableProperties = new Dictionary(); //string:key , object: bindableProperty this.TraverseBindingDataRecursion(ref _dict_BindableProperties, xbehaviour, mvvmService.BindingQueryRecursionDepth, 1, true); //Debug.Log("反射绑定数据完成"); //反射所有Command Dictionary _dict_commands = new Dictionary(); this.GetCommands(ref _dict_commands, xbehaviour); //处理Binder foreach(var binder in binders) { //处理数据消费者 if(binder is IDataConsumer) { this.HandleListenTo(binder, ref handlerComponent, ref _dict_BindableProperties); } //处理数据提供者 if(binder is IDataProducer) { this.HandleProducer(binder, ref handlerComponent, ref _dict_BindableProperties); } //处理事件发射器 if(binder is IEventEmitter) { this.HandleEventEmitter(binder, ref handlerComponent, ref _dict_commands); } } _dict_BindableProperties.Clear(); _dict_BindableProperties = null; _dict_commands.Clear(); _dict_commands = null; return true; } /// /// 遍历绑定数据【递归】 /// /// 绑定数据存储结果 /// 当前数据 /// 最大遍历深度 /// 当前深度 /// 当前层级的基础path /// 仅反射打了"Bindable" attribute的属性 private void TraverseBindingDataRecursion(ref Dictionary resultDict, object currentData, int maxDepth, int currentDepth,bool requireBindableAttribute = false, string currentPath = null) { //判定data对象是否已存在 if (resultDict.Any(kv => kv.Value == currentData)) return; //判定层级深度 if (currentDepth > maxDepth) return; var data_type = currentData.GetType(); if (data_type.HasImplementedRawGeneric(typeof(BindableProperty<>))) { //是BindableProperty<>类,把它添加到字典 if (!resultDict.ContainsKey(currentPath)) { resultDict.Add(currentPath, currentData); } } else { //是一个非“BindableProperty<>”的类,往下一层级作递归 var bindable_properties = data_type.GetProperties(BindingFlags.Public | BindingFlags.Instance); if (requireBindableAttribute) bindable_properties = bindable_properties.Where(p => p.IsDefined(typeof(BindableAttribute))).ToArray(); if(bindable_properties.Length > 0) { foreach(var p in bindable_properties) { var p_data = p.GetValue(currentData); if(p_data != null) { this.TraverseBindingDataRecursion(ref resultDict, p_data, maxDepth, currentDepth + 1, false, (currentPath == null ? p.Name : $"{currentPath}.{p.Name}")); } } } } } /// /// 获取Commands /// /// 存放结果的字典 /// 在某个对象里寻找 /// 存入字典的时候要不要拼接父级Path private void GetCommands(ref Dictionary resultDict, object targetObj, string ParentPath = null) { var targetType = targetObj.GetType(); var methods = targetType.GetMethods(BindingFlags.Public | BindingFlags.Instance); if(methods != null && methods.Length > 0) { foreach(var method in methods) { var attribute = method.GetCustomAttribute(true); if (attribute == null) continue; var parameters = method.GetParameters(); if (parameters.Length != 0) continue; if (method.ReturnType != typeof(void)) continue; Delegate dCommand = Delegate.CreateDelegate(typeof(Action), targetObj, method); string pathName = ParentPath == null ? method.Name : $"{ParentPath}.{method.Name}"; resultDict.AddOrOverride(pathName, dCommand); } } } private void HandleListenTo(BinderBase binder, ref BinderHandlerBaseComponent handlerComponent, ref Dictionary dict_bindableProperties) { string bindingPath = binder.BindingPath; if (dict_bindableProperties.TryGetValue(bindingPath, out object _bindable)) //查找Path { Type bindableType = _bindable.GetType(); //BindableProperty 泛型类型 Type bindablePropertyGenericsType = bindableType.GetGenericArguments().FirstOrDefault(); if (bindablePropertyGenericsType == null) { if (XCore.MainInstance?.IsCmnHans() ?? false) { //中文报错: Debug.LogError($"[TinaX.UIKit.MVVM]绑定路径\"{bindingPath}\"是一个无效的BindableProperty"); } else { Debug.LogError($"[TinaX.UIKit.MVVM]Binding path \"{bindingPath}\"is invalid BindableProperty"); } } //数据消费者的泛型 Type binderType = ((IDataConsumer)binder).GetType(); var binderGenericsType = this.GetDataConsumerType(binderType); if(binderGenericsType == bindablePropertyGenericsType) { //反射生成一个同类型的监听绑定转换器 var converterType = typeof(ListenBindingSameType<>).MakeGenericType(new Type[] { binderGenericsType }); var converter = XCore.MainInstance.CreateInstance(converterType, new object[] { _bindable, binder }); //把生成的绑定转换器交给ViewHandlerComponent来管理生命周期。 handlerComponent.DisposableGroup.Register((IDisposable)converter); } else { //反射生成一个“可绑定属性”与“数据消费者” 类型不一致的绑定转换器 var converterType = typeof(ListenBindingConverter<,>).MakeGenericType(new Type[] { bindablePropertyGenericsType, binderGenericsType }); var converter = XCore.MainInstance.CreateInstance(converterType, new object[] { _bindable, binder }); //把生成的绑定转换器交给ViewHandlerComponent来管理生命周期 handlerComponent.DisposableGroup.Register((IDisposable)converter); } } } /// /// 处理事件发射器 /// private void HandleEventEmitter(BinderBase binder, ref BinderHandlerBaseComponent handlerComponent, ref Dictionary dict_commands) { string bindingPath = binder.BindingPath; if (dict_commands.TryGetValue(bindingPath, out Delegate _delegate)) //查找Path { //执行绑定 EventBindingConverter converter = new EventBindingConverter((IEventEmitter)binder, (Action)_delegate); handlerComponent.DisposableGroup.Register(converter); } } private void HandleProducer(BinderBase binder , ref BinderHandlerBaseComponent handlerComponent, ref Dictionary dict_bindableProperties) { string bindingPath = binder.BindingPath; if (dict_bindableProperties.TryGetValue(bindingPath, out object _bindable)) //查找Path { Type bindableType = _bindable.GetType(); //BindableProperty 泛型类型 Type bindablePropertyGenericsType = bindableType.GetGenericArguments().FirstOrDefault(); if (bindablePropertyGenericsType == null) { if (XCore.MainInstance?.IsCmnHans() ?? false) { //中文报错: Debug.LogError($"[TinaX.UIKit.MVVM]绑定路径\"{bindingPath}\"是一个无效的BindableProperty"); } else { Debug.LogError($"[TinaX.UIKit.MVVM]Binding path \"{bindingPath}\"is invalid BindableProperty"); } } //数据提供者的泛型类型 Type binderType = ((IDataProducer)binder).GetType(); var binderGenericsType = this.GetDataProducerType(binderType); if (binderGenericsType == bindablePropertyGenericsType) { //反射生成一个同类型的监听绑定转换器 var converterType = typeof(ProducerBindingSameType<>).MakeGenericType(new Type[] { binderGenericsType }); var converter = XCore.MainInstance.CreateInstance(converterType, new object[] { _bindable, binder }); //把生成的绑定转换器交给ViewHandlerComponent来管理生命周期。 handlerComponent.DisposableGroup.Register((IDisposable)converter); } else { //反射生成一个“可绑定属性”与“数据消费者” 类型不一致的绑定转换器 var converterType = typeof(ProducerBindingConverter<,>).MakeGenericType(new Type[] { bindablePropertyGenericsType, binderGenericsType }); var converter = XCore.MainInstance.CreateInstance(converterType, new object[] { _bindable, binder }); //把生成的绑定转换器交给ViewHandlerComponent来管理生命周期 handlerComponent.DisposableGroup.Register((IDisposable)converter); } } } /// /// 获取数据消费者的泛型类型 /// /// private Type GetDataConsumerType(Type type) { if (type == null) throw new ArgumentNullException(nameof(type)); var interfaces = type.GetInterfaces(); if (interfaces == null || interfaces.Length < 1) return null; foreach(var i in interfaces) { if (i.IsGenericType) { if(typeof(IDataConsumer).IsAssignableFrom(i)) { return i.GetGenericArguments().FirstOrDefault(); } } } return null; } /// /// 获取数据提供者的泛型类型 /// /// /// private Type GetDataProducerType(Type type) { if (type == null) throw new ArgumentNullException(nameof(type)); var interfaces = type.GetInterfaces(); if (interfaces == null || interfaces.Length < 1) return null; foreach (var i in interfaces) { if (i.IsGenericType) { if (typeof(IDataProducer).IsAssignableFrom(i)) { return i.GetGenericArguments().FirstOrDefault(); } } } return null; } } }