public static void InvokeMethodOrProperty(InvokeDescriptor invokeDescriptor, UnityEngine.Object instance)
        {
            if (!instance)
            {
                return;
            }

            if (string.IsNullOrEmpty(invokeDescriptor.MethodName) && string.IsNullOrEmpty(invokeDescriptor.PropertyName))
            {
                return;
            }

            var type = instance.GetType();

            if (string.IsNullOrEmpty(invokeDescriptor.MethodName))
            {
                var propertyInfo = type.GetProperty(invokeDescriptor.PropertyName);
                propertyInfo.SetValue(instance, invokeDescriptor.Param.Get(), null);
            }
            else
            {
                Type[] types;
                if (invokeDescriptor.Param.ParamType == InvokeParam.Type.None)
                {
                    types = new Type[0];
                }
                else
                {
                    types = new[] { invokeDescriptor.Param.Get().GetType() };
                }

                var methodInfo = type.GetMethod(invokeDescriptor.MethodName, types);
                if (types.Length == 0)
                {
                    methodInfo.Invoke(instance, null);
                }
                else
                {
                    singleParamContainer[0] = invokeDescriptor.Param.Get();
                    methodInfo.Invoke(instance, singleParamContainer);
                }
            }
        }
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            descriptors = TypeHelper.CollectValidMeshodAndField(templateGO);
            descriptor  = GetTargetObjectWithProperty(property) as InvokeDescriptor;
            Rect functionSelect = position;

            functionSelect.x     += 120;
            functionSelect.width -= 120;
            functionSelect.height = EditorGUIUtility.singleLineHeight;

            if (descriptors == null)
            {
                GUI.enabled = false;
                EditorGUI.DropdownButton(functionSelect, new GUIContent(descriptor.ToString()), FocusType.Passive);
                GUI.enabled = true;
            }
            else
            {
                if (EditorGUI.DropdownButton(functionSelect, new GUIContent(descriptor.ToString()), FocusType.Passive))
                {
                    GenericMenu menu = new GenericMenu();
                    menu.AddItem(new GUIContent("No Function"), descriptor == null, OnDescriptorSelected, new Context()
                    {
                        Current  = descriptor,
                        Selected = null
                    });
                    menu.AddSeparator("");

                    foreach (var desc in descriptors)
                    {
                        menu.AddItem(new GUIContent(desc.MenuPath), desc == descriptor, OnDescriptorSelected, new Context()
                        {
                            Current  = descriptor,
                            Selected = desc
                        });
                    }

                    functionSelect.y -= EditorGUIUtility.singleLineHeight;
                    menu.DropDown(functionSelect);
                }
            }

            // next line
            position.y += EditorGUIUtility.singleLineHeight;
            templateGO  = (GameObject)EditorGUI.ObjectField(new Rect(position.x, position.y, 120, EditorGUIUtility.singleLineHeight), templateGO, typeof(GameObject), true);

            var valueRect = new Rect(position);

            valueRect.x     += 120;
            valueRect.width -= 120;
            valueRect.height = EditorGUIUtility.singleLineHeight;
            if (descriptor.IsActive)
            {
                switch (descriptor.Param.ParamType)
                {
                case InvokeParam.Type.Integer:
                    descriptor.Param.Integer = EditorGUI.IntField(valueRect, descriptor.Param.Integer);
                    break;

                case InvokeParam.Type.Float:
                case InvokeParam.Type.Double:
                    descriptor.Param.Float = EditorGUI.DoubleField(valueRect, descriptor.Param.Float);
                    break;

                case InvokeParam.Type.Boolean:
                    descriptor.Param.Boolean = EditorGUI.Toggle(valueRect, descriptor.Param.Boolean);
                    break;

                case InvokeParam.Type.String:
                    descriptor.Param.String = EditorGUI.TextField(valueRect, descriptor.Param.String);
                    break;

                case InvokeParam.Type.Object:
                    descriptor.Param.Object = EditorGUI.ObjectField(valueRect, descriptor.Param.Object, typeof(Object), false);
                    break;

                case InvokeParam.Type.None:
                    break;
                }
            }
        }