UnityMemberHelper.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Runtime.CompilerServices;
  6. using UnityObject = UnityEngine.Object;
  7. namespace Chronos.Reflection.Internal
  8. {
  9. internal static class UnityMemberHelper
  10. {
  11. internal static bool TryReflectMethod(out MethodInfo methodInfo, out UnityReflectionException exception, UnityObject reflectionTarget, string name, Type[] parameterTypes)
  12. {
  13. #if !NETFX_CORE
  14. methodInfo = null;
  15. Type type = reflectionTarget.GetType();
  16. BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy;
  17. if (parameterTypes != null) // Explicit matching
  18. {
  19. methodInfo = type.GetMethod(name, flags, null, parameterTypes, null);
  20. if (methodInfo == null)
  21. {
  22. methodInfo = type.GetExtensionMethods()
  23. .Where(extension => extension.Name == name)
  24. .Where(extension => Enumerable.SequenceEqual(extension.GetParameters().Select(paramInfo => paramInfo.ParameterType), parameterTypes))
  25. .FirstOrDefault();
  26. }
  27. if (methodInfo == null)
  28. {
  29. exception = new UnityReflectionException(string.Format("No matching method found: '{0}.{1} ({2})'", type.Name, name, string.Join(", ", parameterTypes.Select(t => t.Name).ToArray())));
  30. return false;
  31. }
  32. }
  33. else // Implicit matching
  34. {
  35. var normalMethods = type.GetMember(name, MemberTypes.Method, flags).OfType<MethodInfo>().ToList();
  36. var extensionMethods = type.GetExtensionMethods().Where(extension => extension.Name == name).ToList();
  37. var methods = new List<MethodInfo>();
  38. methods.AddRange(normalMethods);
  39. methods.AddRange(extensionMethods);
  40. if (methods.Count == 0)
  41. {
  42. exception = new UnityReflectionException(string.Format("No matching method found: '{0}.{1}'", type.Name, name));
  43. return false;
  44. }
  45. if (methods.Count > 1)
  46. {
  47. exception = new UnityReflectionException(string.Format("Multiple method signatures found for '{0}.{1}'\nSpecify the parameter types explicitly.", type.FullName, name));
  48. return false;
  49. }
  50. methodInfo = methods[0];
  51. }
  52. exception = null;
  53. return true;
  54. #else
  55. throw new Exception("Reflection is not supported in .NET Core.");
  56. #endif
  57. }
  58. internal static MethodInfo ReflectMethod(UnityObject reflectionTarget, string name, Type[] parameterTypes)
  59. {
  60. MethodInfo methodInfo;
  61. UnityReflectionException exception;
  62. if (!TryReflectMethod(out methodInfo, out exception, reflectionTarget, name, parameterTypes))
  63. {
  64. throw exception;
  65. }
  66. return methodInfo;
  67. }
  68. internal static object InvokeMethod(UnityObject reflectionTarget, MethodInfo methodInfo, bool isExtension, params object[] parameters)
  69. {
  70. if (isExtension)
  71. {
  72. var fullParameters = new object[parameters.Length + 1];
  73. fullParameters[0] = reflectionTarget;
  74. Array.Copy(parameters, 0, fullParameters, 1, parameters.Length);
  75. parameters = fullParameters;
  76. }
  77. return methodInfo.Invoke(reflectionTarget, parameters);
  78. }
  79. internal static bool TryReflectVariable(out MemberInfo variableInfo, out UnityReflectionException exception, UnityObject reflectionTarget, string name)
  80. {
  81. #if !NETFX_CORE
  82. variableInfo = null;
  83. Type type = reflectionTarget.GetType();
  84. MemberTypes types = MemberTypes.Property | MemberTypes.Field;
  85. BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy;
  86. MemberInfo[] variables = type.GetMember(name, types, flags);
  87. if (variables.Length == 0)
  88. {
  89. exception = new UnityReflectionException(string.Format("No matching field or property found: '{0}.{1}'", type.Name, name));
  90. return false;
  91. }
  92. variableInfo = variables[0]; // Safe, because there can't possibly be more than one variable of the same name
  93. exception = null;
  94. return true;
  95. #else
  96. throw new Exception("Reflection is not supported in .NET Core.");
  97. #endif
  98. }
  99. internal static MemberInfo ReflectVariable(UnityObject reflectionTarget, string name)
  100. {
  101. MemberInfo variableInfo;
  102. UnityReflectionException exception;
  103. if (!TryReflectVariable(out variableInfo, out exception, reflectionTarget, name))
  104. {
  105. throw exception;
  106. }
  107. return variableInfo;
  108. }
  109. }
  110. }