public void DoBind(VMBehaviour vm, object parameter, GameObject obj, Component component) { if (component == null) { Debugger.LogError("CommandBinder", obj.name + " component null."); return; } if (string.IsNullOrEmpty(this.Command)) { Debugger.LogError("CommandBinder", obj.name + " command key empty."); return; } if (string.IsNullOrEmpty(this.Event)) { Debugger.LogError("CommandBinder", obj.name + " event key empty."); return; } // component type reflection componentType = component.GetType(); componentReflection = ReflectionCache.Singleton[componentType]; // command type reflection command = vm.GetCommand(this.Command); if (command == null) { Debugger.LogError("CommandBinder", obj.name + " command null."); return; } commandType = command.GetType().BaseType; if (!typeof(BaseCommand).IsAssignableFrom(commandType)) { Debugger.LogError("CommandBinder", obj.name + " command type error."); return; } commandReflection = ReflectionCache.Singleton[commandType]; // source event type reflection // TODO: 性能优化 GetValue // UGUI 组件的 event 有的是 property,有的不是,所以 field 和 property 都判断 FieldInfo sourceEventFieldInfo = componentReflection.GetField(this.Event); PropertyInfo sourceEventPropertyInfo = componentReflection.GetProperty(this.Event); if (sourceEventFieldInfo != null) { sourceEventType = sourceEventFieldInfo.FieldType.BaseType; sourceEventObj = sourceEventFieldInfo.GetValue(component); } if (sourceEventPropertyInfo != null) { sourceEventType = sourceEventPropertyInfo.PropertyType.BaseType; sourceEventObj = sourceEventPropertyInfo.GetValue(component); } if (sourceEventType == null || sourceEventObj == null) { Debugger.LogError("CommandBinder", obj.name + " event null."); return; } if (!typeof(UnityEngine.Events.UnityEventBase).IsAssignableFrom(sourceEventType)) { Debugger.LogError("CommandBinder", obj.name + " event type error."); return; } sourceEventReflection = ReflectionCache.Singleton[sourceEventType]; // 判断 event 和 command 参数类型是否匹配 bool genericTypeExplicit = true; while (true) { if (sourceEventType.IsGenericType != commandType.IsGenericType) { genericTypeExplicit = false; break; } Type[] sourceEventGenericTypes = sourceEventReflection.GetGenericArguments(); Type[] commandGenericTypes = commandReflection.GetGenericArguments(); if (sourceEventGenericTypes.Length != commandGenericTypes.Length) { genericTypeExplicit = false; break; } for (int j = 0; j < sourceEventGenericTypes.Length; j++) { if (sourceEventGenericTypes[j] != commandGenericTypes[j]) { genericTypeExplicit = false; break; } } break; } if (!genericTypeExplicit) { Debugger.LogError("CommandBinder", obj.name + " event type and command type not explicit."); return; } command.BindVM(vm); sourceEventAction = command.AddListenerToEvent(sourceEventObj, parameter); Selectable selectableComponent = component as Selectable; if (selectableComponent != null) { canExecuteHandler = new Action(delegate { selectableComponent.interactable = command.CanExecute(parameter); }); command.AddCanExecuteChangedListener(canExecuteHandler); selectableComponent.interactable = command.CanExecute(parameter); } }
private void DoPropertyBind(VMBehaviour vm, GameObject obj) { if (this.Component == null) { Debugger.LogError("DataBinder", obj.name + " component null."); return; } if (string.IsNullOrEmpty(this.Property)) { Debugger.LogError("DataBinder", obj.name + " property empty."); return; } if (componentType == null) { componentType = this.Component.GetType(); componentReflection = ReflectionCache.Singleton[componentType]; } PropertyInfo propertyInfo = componentReflection.GetProperty(this.Property); if (propertyInfo == null || propertyInfo.GetSetMethod() == null) { Debugger.LogError("DataBinder", obj.name + " property null or not support."); return; } Type propertyType = propertyInfo.PropertyType; if (!CheckDataTypeValid(propertyType, obj)) { return; } ISetValue propertySetter = SetterWrapper.CreatePropertySetterWrapper(propertyInfo); if (propertySetter == null) { return; } // 数据单向绑定 this.SetValueHandler = delegate(IData source) { object value = this.Source.FastGetValue(); if (this.Converter != null) { value = this.Converter.Convert(value, propertyType, this.Definer.ConverterParameter, vm); } propertySetter.Set(this.Component, value); // ToggleGroup 特殊处理 if (Toggle_Type.IsAssignableFrom(componentType) && this.Property.Equals("isOn")) { Toggle t = this.Component as Toggle; if (t.group != null && t.isOn) { try { t.group.NotifyToggleOn(t); } catch (System.Exception) { } } } }; this.Source.AddValueChangedListener(this.SetValueHandler); this.SetValueHandler.Invoke(this.Source); // 可交互组件的双向绑定 if (Toggle_Type.IsAssignableFrom(componentType) && this.Property.Equals("isOn")) { this.ValueChangedHandler = new UnityAction <bool>(delegate(bool arg) { if (this.Converter != null) { object value = this.Converter.ConvertBack(arg, this.Source.GetBindDataType(), this.Definer.ConverterParameter, vm); this.Source.FastSetValue(value); } else { (this.Source as BaseData <bool>).Set(arg); } }); (this.Component as Toggle).onValueChanged.AddListener((UnityAction <bool>) this.ValueChangedHandler); } if (Input_Type.IsAssignableFrom(componentType) && this.Property.Equals("text")) { this.ValueChangedHandler = new UnityAction <string>(delegate(string arg) { if (this.Converter != null) { object value = this.Converter.ConvertBack(arg, this.Source.GetBindDataType(), this.Definer.ConverterParameter, vm); this.Source.FastSetValue(value); } else { (this.Source as BaseData <string>).Set(arg); } }); (this.Component as InputField).onValueChanged.AddListener((UnityAction <string>) this.ValueChangedHandler); } if (Dropdown_Type.IsAssignableFrom(componentType) && this.Property.Equals("value")) { this.ValueChangedHandler = new UnityAction <int>(delegate(int arg) { if (this.Converter != null) { object value = this.Converter.ConvertBack(arg, this.Source.GetBindDataType(), this.Definer.ConverterParameter, vm); this.Source.FastSetValue(value); } else { (this.Source as BaseData <int>).Set(arg); } }); (this.Component as Dropdown).onValueChanged.AddListener((UnityAction <int>) this.ValueChangedHandler); } if (Slider_Type.IsAssignableFrom(componentType) && this.Property.Equals("value")) { this.ValueChangedHandler = new UnityAction <float>(delegate(float arg) { if (this.Converter != null) { object value = this.Converter.ConvertBack(arg, this.Source.GetBindDataType(), this.Definer.ConverterParameter, vm); this.Source.FastSetValue(value); } else { (this.Source as BaseData <float>).Set(arg); } }); (this.Component as Slider).onValueChanged.AddListener((UnityAction <float>) this.ValueChangedHandler); } }