ReflectionHelper.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using UnityEditor;
  5. using UnityEngine;
  6. namespace EnhancedHierarchy {
  7. /// <summary>
  8. /// Class containing method extensions for getting private and internal members.
  9. /// </summary>
  10. public static partial class ReflectionHelper {
  11. public const BindingFlags FULL_BINDING = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
  12. public const BindingFlags INSTANCE_BINDING = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
  13. public const BindingFlags STATIC_BINDING = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;
  14. private static Assembly[] cachedAssemblies;
  15. private static Dictionary<string, Type> cachedTypes;
  16. public static Type FindType(string name) {
  17. Type result;
  18. if (cachedTypes == null)
  19. cachedTypes = new Dictionary<string, Type>();
  20. if (cachedTypes.TryGetValue(name, out result))
  21. return result;
  22. result = FindTypeInAssembly(name, typeof(Editor).Assembly);
  23. if (result == null) {
  24. if (cachedAssemblies == null)
  25. cachedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
  26. for (var i = 0; i < cachedAssemblies.Length; i++) {
  27. result = FindTypeInAssembly(name, cachedAssemblies[i]);
  28. if (result != null)
  29. break;
  30. }
  31. }
  32. if (Preferences.DebugEnabled)
  33. if (result == null)
  34. Debug.LogFormat("Cache fault for \"{0}\", type not found", name);
  35. else
  36. Debug.LogFormat("Cache fault for \"{0}\", found type at \"{1}\"", name, result.Assembly.Location);
  37. cachedTypes[name] = result;
  38. return result;
  39. }
  40. private static Type FindTypeInAssembly(string name, Assembly assembly) {
  41. return assembly == null ?
  42. null :
  43. assembly.GetType(name, false, true);
  44. }
  45. public static FieldInfo FindField(this Type type, string fieldName, BindingFlags flags = FULL_BINDING) {
  46. return type.GetField(fieldName, flags);
  47. }
  48. public static PropertyInfo FindProperty(this Type type, string propertyName, BindingFlags flags = FULL_BINDING) {
  49. return type.GetProperty(propertyName, flags);
  50. }
  51. public static MethodInfo FindMethod(this Type type, string methodName, Type[] argsTypes = null, BindingFlags flags = FULL_BINDING) {
  52. return argsTypes == null ?
  53. type.GetMethod(methodName, flags) :
  54. type.GetMethod(methodName, flags, null, argsTypes, null);
  55. }
  56. #region Fields
  57. public static T GetStaticField<T>(this Type type, string fieldName) {
  58. if (type == null)
  59. throw new ArgumentNullException("type");
  60. return (T)type.FindField(fieldName, STATIC_BINDING).GetValue(null);
  61. }
  62. public static T GetInstanceField<T>(this object obj, string fieldName) {
  63. if (obj == null)
  64. throw new ArgumentNullException("obj");
  65. return (T)obj.GetType().FindField(fieldName, INSTANCE_BINDING).GetValue(obj);
  66. }
  67. public static void SetStaticField<TValue>(this Type type, string fieldName, TValue value) {
  68. if (type == null)
  69. throw new ArgumentNullException("type");
  70. type.FindField(fieldName, STATIC_BINDING).SetValue(null, value);
  71. }
  72. public static void SetInstanceField<TObj, TValue>(this TObj obj, string fieldName, TValue value) {
  73. if (obj == null)
  74. throw new ArgumentNullException("obj");
  75. obj.GetType().FindField(fieldName, INSTANCE_BINDING).SetValue(obj, value);
  76. }
  77. public static bool HasField(this Type type, string fieldName) {
  78. return type.FindField(fieldName) != null;
  79. }
  80. public static bool HasField<T>(this T obj, string fieldName) {
  81. return obj.GetType().HasField(fieldName);
  82. }
  83. #endregion
  84. #region Props
  85. public static T GetStaticProperty<T>(this Type type, string propertyName) {
  86. if (type == null)
  87. throw new ArgumentNullException("type");
  88. return (T)type.FindProperty(propertyName, STATIC_BINDING).GetValue(null, null);
  89. }
  90. public static T GetInstanceProperty<T>(this object obj, string propertyName) {
  91. if (obj == null)
  92. throw new ArgumentNullException("obj");
  93. return (T)obj.GetType().FindProperty(propertyName, INSTANCE_BINDING).GetValue(obj, null);
  94. }
  95. public static void SetStaticProperty<TValue>(this Type type, string propertyName, TValue value) {
  96. if (type == null)
  97. throw new ArgumentNullException("type");
  98. type.FindProperty(propertyName, STATIC_BINDING).SetValue(null, value, null);
  99. }
  100. public static void SetInstanceProperty<TObj, TValue>(this TObj obj, string propertyName, TValue value) {
  101. if (obj == null)
  102. throw new ArgumentNullException("obj");
  103. obj.GetType().FindProperty(propertyName, INSTANCE_BINDING).SetValue(obj, value, null);
  104. }
  105. public static bool HasProperty(this Type type, string propertyName) {
  106. return type.FindProperty(propertyName) != null;
  107. }
  108. public static bool HasProperty<T>(this T obj, string propertyName) {
  109. return obj.GetType().HasProperty(propertyName);
  110. }
  111. #endregion
  112. public static object RawCall(Type type, object obj, string methodName, object[] args, Type[] argsTypes, bool isStatic) {
  113. if (obj == null && !isStatic)
  114. throw new ArgumentNullException("obj", "obj cannot be null for instance methods");
  115. if (type == null)
  116. throw new ArgumentNullException("type");
  117. for (var i = 0; i < argsTypes.Length; i++)
  118. if (argsTypes[i] == typeof(object))
  119. argsTypes[i] = args[i].GetType();
  120. var method = type.FindMethod(methodName, argsTypes, isStatic ? STATIC_BINDING : INSTANCE_BINDING);
  121. if (method == null)
  122. throw new MissingMethodException(type.FullName, methodName);
  123. return method.Invoke(obj, args);
  124. }
  125. #region Invoke Instance
  126. public static void InvokeMethod(this object obj, string methodName) {
  127. var args = new object[] { };
  128. var argsTypes = new Type[] { };
  129. RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  130. }
  131. public static void InvokeMethod<TArg1>(this object obj, string methodName, TArg1 arg1) {
  132. var args = new object[] { arg1 };
  133. var argsTypes = new Type[] { typeof(TArg1) };
  134. RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  135. }
  136. public static void InvokeMethod<TArg1, TArg2>(this object obj, string methodName, TArg1 arg1, TArg2 arg2) {
  137. var args = new object[] { arg1, arg2 };
  138. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) };
  139. RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  140. }
  141. public static void InvokeMethod<TArg1, TArg2, TArg3>(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) {
  142. var args = new object[] { arg1, arg2, arg3 };
  143. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) };
  144. RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  145. }
  146. public static void InvokeMethod<TArg1, TArg2, TArg3, TArg4>(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) {
  147. var args = new object[] { arg1, arg2, arg3, arg4 };
  148. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) };
  149. RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  150. }
  151. public static TResult InvokeMethod<TResult>(this object obj, string methodName) {
  152. var args = new object[] { };
  153. var argsTypes = new Type[] { };
  154. return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  155. }
  156. public static TResult InvokeMethod<TResult, TArg1>(this object obj, string methodName, TArg1 arg1) {
  157. var args = new object[] { arg1 };
  158. var argsTypes = new Type[] { typeof(TArg1) };
  159. return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  160. }
  161. public static TResult InvokeMethod<TResult, TArg1, TArg2>(this object obj, string methodName, TArg1 arg1, TArg2 arg2) {
  162. var args = new object[] { arg1, arg2 };
  163. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) };
  164. return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  165. }
  166. public static TResult InvokeMethod<TResult, TArg1, TArg2, TArg3>(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) {
  167. var args = new object[] { arg1, arg2, arg3 };
  168. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) };
  169. return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  170. }
  171. public static TResult InvokeMethod<TResult, TArg1, TArg2, TArg3, TArg4>(this object obj, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) {
  172. var args = new object[] { arg1, arg2, arg3, arg4 };
  173. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) };
  174. return (TResult)RawCall(obj.GetType(), obj, methodName, args, argsTypes, false);
  175. }
  176. #endregion
  177. #region Invoke Static
  178. public static void InvokeStaticMethod(this Type type, string methodName) {
  179. var args = new object[] { };
  180. var argsTypes = new Type[] { };
  181. RawCall(type, null, methodName, args, argsTypes, true);
  182. }
  183. public static void InvokeStaticMethod<TArg1>(this Type type, string methodName, TArg1 arg1) {
  184. var args = new object[] { arg1 };
  185. var argsTypes = new Type[] { typeof(TArg1) };
  186. RawCall(type, null, methodName, args, argsTypes, true);
  187. }
  188. public static void InvokeStaticMethod<TArg1, TArg2>(this Type type, string methodName, TArg1 arg1, TArg2 arg2) {
  189. var args = new object[] { arg1, arg2 };
  190. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) };
  191. RawCall(type, null, methodName, args, argsTypes, true);
  192. }
  193. public static void InvokeStaticMethod<TArg1, TArg2, TArg3>(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) {
  194. var args = new object[] { arg1, arg2, arg3 };
  195. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) };
  196. RawCall(type, null, methodName, args, argsTypes, true);
  197. }
  198. public static void InvokeStaticMethod<TArg1, TArg2, TArg3, TArg4>(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) {
  199. var args = new object[] { arg1, arg2, arg3, arg4 };
  200. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) };
  201. RawCall(type, null, methodName, args, argsTypes, true);
  202. }
  203. public static TResult InvokeStaticMethod<TResult>(this Type type, string methodName) {
  204. var args = new object[] { };
  205. var argsTypes = new Type[] { };
  206. return (TResult)RawCall(type, null, methodName, args, argsTypes, true);
  207. }
  208. public static TResult InvokeStaticMethod<TResult, TArg1>(this Type type, string methodName, TArg1 arg1) {
  209. var args = new object[] { arg1 };
  210. var argsTypes = new Type[] { typeof(TArg1) };
  211. return (TResult)RawCall(type, null, methodName, args, argsTypes, true);
  212. }
  213. public static TResult InvokeStaticMethod<TResult, TArg1, TArg2>(this Type type, string methodName, TArg1 arg1, TArg2 arg2) {
  214. var args = new object[] { arg1, arg2 };
  215. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) };
  216. return (TResult)RawCall(type, null, methodName, args, argsTypes, true);
  217. }
  218. public static TResult InvokeStaticMethod<TResult, TArg1, TArg2, TArg3>(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3) {
  219. var args = new object[] { arg1, arg2, arg3 };
  220. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) };
  221. return (TResult)RawCall(type, null, methodName, args, argsTypes, true);
  222. }
  223. public static TResult InvokeStaticMethod<TResult, TArg1, TArg2, TArg3, TArg4>(this Type type, string methodName, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) {
  224. var args = new object[] { arg1, arg2, arg3, arg4 };
  225. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) };
  226. return (TResult)RawCall(type, null, methodName, args, argsTypes, true);
  227. }
  228. #endregion
  229. #region Has Method
  230. public static bool HasMethod(this object obj, string methodName) {
  231. var argsTypes = new Type[] { };
  232. return obj.GetType().FindMethod(methodName, argsTypes) != null;
  233. }
  234. public static bool HasMethod<TArg1>(this object obj, string methodName) {
  235. var argsTypes = new Type[] { typeof(TArg1) };
  236. return obj.GetType().FindMethod(methodName, argsTypes) != null;
  237. }
  238. public static bool HasMethod<TArg1, TArg2>(this object obj, string methodName) {
  239. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) };
  240. return obj.GetType().FindMethod(methodName, argsTypes) != null;
  241. }
  242. public static bool HasMethod<TArg1, TArg2, TArg3>(this object obj, string methodName) {
  243. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) };
  244. return obj.GetType().FindMethod(methodName, argsTypes) != null;
  245. }
  246. public static bool HasMethod<TArg1, TArg2, TArg3, TArg4>(this object obj, string methodName) {
  247. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) };
  248. return obj.GetType().FindMethod(methodName, argsTypes) != null;
  249. }
  250. public static bool HasMethod(this Type type, string methodName) {
  251. var argsTypes = new Type[] { };
  252. return type.FindMethod(methodName, argsTypes) != null;
  253. }
  254. public static bool HasMethod<TArg1>(this Type type, string methodName) {
  255. var argsTypes = new Type[] { typeof(TArg1) };
  256. return type.FindMethod(methodName, argsTypes) != null;
  257. }
  258. public static bool HasMethod<TArg1, TArg2>(this Type type, string methodName) {
  259. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2) };
  260. return type.FindMethod(methodName, argsTypes) != null;
  261. }
  262. public static bool HasMethod<TArg1, TArg2, TArg3>(this Type type, string methodName) {
  263. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) };
  264. return type.FindMethod(methodName, argsTypes) != null;
  265. }
  266. public static bool HasMethod<TArg1, TArg2, TArg3, TArg4>(this Type type, string methodName) {
  267. var argsTypes = new Type[] { typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) };
  268. return type.FindMethod(methodName, argsTypes) != null;
  269. }
  270. #endregion
  271. }
  272. }