using System; using System.Collections.Generic; using System.Reflection; using UnityEditor; using UnityEngine; namespace EnhancedHierarchy { /// /// Class containing method extensions for getting private and internal members. /// public static partial class ReflectionHelper { public const BindingFlags FULL_BINDING = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public const BindingFlags INSTANCE_BINDING = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; public const BindingFlags STATIC_BINDING = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public; private static Assembly[] cachedAssemblies; private static Dictionary cachedTypes; public static Type FindType(string name) { Type result; if (cachedTypes == null) cachedTypes = new Dictionary(); if (cachedTypes.TryGetValue(name, out result)) return result; result = FindTypeInAssembly(name, typeof(Editor).Assembly); if (result == null) { if (cachedAssemblies == null) cachedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); for (var i = 0; i < cachedAssemblies.Length; i++) { result = FindTypeInAssembly(name, cachedAssemblies[i]); if (result != null) break; } } if (Preferences.DebugEnabled) if (result == null) Debug.LogFormat("Cache fault for \"{0}\", type not found", name); else Debug.LogFormat("Cache fault for \"{0}\", found type at \"{1}\"", name, result.Assembly.Location); cachedTypes[name] = result; return result; } private static Type FindTypeInAssembly(string name, Assembly assembly) { return assembly == null ? null : assembly.GetType(name, false, true); } public static FieldInfo FindField(this Type type, string fieldName, BindingFlags flags = FULL_BINDING) { return type.GetField(fieldName, flags); } public static PropertyInfo FindProperty(this Type type, string propertyName, BindingFlags flags = FULL_BINDING) { return type.GetProperty(propertyName, flags); } public static MethodInfo FindMethod(this Type type, string methodName, Type[] argsTypes = null, BindingFlags flags = FULL_BINDING) { return argsTypes == null ? type.GetMethod(methodName, flags) : type.GetMethod(methodName, flags, null, argsTypes, null); } #region Fields public static T GetStaticField(this Type type, string fieldName) { if (type == null) throw new ArgumentNullException("type"); return (T)type.FindField(fieldName, STATIC_BINDING).GetValue(null); } public static T GetInstanceField(this object obj, string fieldName) { if (obj == null) throw new ArgumentNullException("obj"); return (T)obj.GetType().FindField(fieldName, INSTANCE_BINDING).GetValue(obj); } public static void SetStaticField(this Type type, string fieldName, TValue value) { if (type == null) throw new ArgumentNullException("type"); type.FindField(fieldName, STATIC_BINDING).SetValue(null, value); } public static void SetInstanceField(this TObj obj, string fieldName, TValue value) { if (obj == null) throw new ArgumentNullException("obj"); obj.GetType().FindField(fieldName, INSTANCE_BINDING).SetValue(obj, value); } public static bool HasField(this Type type, string fieldName) { return type.FindField(fieldName) != null; } public static bool HasField(this T obj, string fieldName) { return obj.GetType().HasField(fieldName); } #endregion #region Props public static T GetStaticProperty(this Type type, string propertyName) { if (type == null) throw new ArgumentNullException("type"); return (T)type.FindProperty(propertyName, STATIC_BINDING).GetValue(null, null); } public static T GetInstanceProperty(this object obj, string propertyName) { if (obj == null) throw new ArgumentNullException("obj"); return (T)obj.GetType().FindProperty(propertyName, INSTANCE_BINDING).GetValue(obj, null); } public static void SetStaticProperty(this Type type, string propertyName, TValue value) { if (type == null) throw new ArgumentNullException("type"); type.FindProperty(propertyName, STATIC_BINDING).SetValue(null, value, null); } public static void SetInstanceProperty(this TObj obj, string propertyName, TValue value) { if (obj == null) throw new ArgumentNullException("obj"); obj.GetType().FindProperty(propertyName, INSTANCE_BINDING).SetValue(obj, value, null); } public static bool HasProperty(this Type type, string propertyName) { return type.FindProperty(propertyName) != null; } public static bool HasProperty(this T obj, string propertyName) { return obj.GetType().HasProperty(propertyName); } #endregion public static object RawCall(Type type, object obj, string methodName, object[] args, Type[] argsTypes, bool isStatic) { if (obj == null && !isStatic) throw new ArgumentNullException("obj", "obj cannot be null for instance methods"); if (type == null) throw new ArgumentNullException("type"); for (var i = 0; i < argsTypes.Length; i++) if (argsTypes[i] == typeof(object)) argsTypes[i] = args[i].GetType(); var method = type.FindMethod(methodName, argsTypes, isStatic ? STATIC_BINDING : INSTANCE_BINDING); if (method == null) throw new MissingMethodException(type.FullName, methodName); return method.Invoke(obj, args); } #region Invoke Instance public static void InvokeMethod(this object obj, string methodName) { var args = new object[] { }; var argsTypes = new Type[] { }; RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static void InvokeMethod(this object obj, string methodName, TArg1 arg1) { var args = new object[] { arg1 }; var argsTypes = new Type[] { typeof(TArg1) }; RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static void InvokeMethod(this object obj, string methodName, TArg1 arg1, TArg2 arg2) { var args = new object[] { arg1, arg2 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) }; RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static void InvokeMethod(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) { var args = new object[] { arg1, arg2, arg3 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) }; RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static void InvokeMethod(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) { var args = new object[] { arg1, arg2, arg3, arg4 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) }; RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static TResult InvokeMethod(this object obj, string methodName) { var args = new object[] { }; var argsTypes = new Type[] { }; return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static TResult InvokeMethod(this object obj, string methodName, TArg1 arg1) { var args = new object[] { arg1 }; var argsTypes = new Type[] { typeof(TArg1) }; return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static TResult InvokeMethod(this object obj, string methodName, TArg1 arg1, TArg2 arg2) { var args = new object[] { arg1, arg2 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) }; return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static TResult InvokeMethod(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) { var args = new object[] { arg1, arg2, arg3 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) }; return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } public static TResult InvokeMethod(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) { var args = new object[] { arg1, arg2, arg3, arg4 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) }; return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false); } #endregion #region Invoke Static public static void InvokeStaticMethod(this Type type, string methodName) { var args = new object[] { }; var argsTypes = new Type[] { }; RawCall(type, null, methodName, args, argsTypes, true); } public static void InvokeStaticMethod(this Type type, string methodName, TArg1 arg1) { var args = new object[] { arg1 }; var argsTypes = new Type[] { typeof(TArg1) }; RawCall(type, null, methodName, args, argsTypes, true); } public static void InvokeStaticMethod(this Type type, string methodName, TArg1 arg1, TArg2 arg2) { var args = new object[] { arg1, arg2 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) }; RawCall(type, null, methodName, args, argsTypes, true); } public static void InvokeStaticMethod(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) { var args = new object[] { arg1, arg2, arg3 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) }; RawCall(type, null, methodName, args, argsTypes, true); } public static void InvokeStaticMethod(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) { var args = new object[] { arg1, arg2, arg3, arg4 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) }; RawCall(type, null, methodName, args, argsTypes, true); } public static TResult InvokeStaticMethod(this Type type, string methodName) { var args = new object[] { }; var argsTypes = new Type[] { }; return (TResult)RawCall(type, null, methodName, args, argsTypes, true); } public static TResult InvokeStaticMethod(this Type type, string methodName, TArg1 arg1) { var args = new object[] { arg1 }; var argsTypes = new Type[] { typeof(TArg1) }; return (TResult)RawCall(type, null, methodName, args, argsTypes, true); } public static TResult InvokeStaticMethod(this Type type, string methodName, TArg1 arg1, TArg2 arg2) { var args = new object[] { arg1, arg2 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) }; return (TResult)RawCall(type, null, methodName, args, argsTypes, true); } public static TResult InvokeStaticMethod(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) { var args = new object[] { arg1, arg2, arg3 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) }; return (TResult)RawCall(type, null, methodName, args, argsTypes, true); } public static TResult InvokeStaticMethod(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) { var args = new object[] { arg1, arg2, arg3, arg4 }; var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) }; return (TResult)RawCall(type, null, methodName, args, argsTypes, true); } #endregion #region Has Method public static bool HasMethod(this object obj, string methodName) { var argsTypes = new Type[] { }; return obj.GetType().FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this object obj, string methodName) { var argsTypes = new Type[] { typeof(TArg1) }; return obj.GetType().FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this object obj, string methodName) { var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) }; return obj.GetType().FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this object obj, string methodName) { var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) }; return obj.GetType().FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this object obj, string methodName) { var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) }; return obj.GetType().FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this Type type, string methodName) { var argsTypes = new Type[] { }; return type.FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this Type type, string methodName) { var argsTypes = new Type[] { typeof(TArg1) }; return type.FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this Type type, string methodName) { var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) }; return type.FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this Type type, string methodName) { var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) }; return type.FindMethod(methodName, argsTypes) != null; } public static bool HasMethod(this Type type, string methodName) { var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) }; return type.FindMethod(methodName, argsTypes) != null; } #endregion } }