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); } }