You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
4.4 KiB

  1. using System;
  2. using System.Reflection;
  3. using UnityEngine;
  4. namespace IllusionPlugin.Utils
  5. {
  6. /// <summary>
  7. /// A utility class providing reflection helper methods.
  8. /// </summary>
  9. public static class ReflectionUtil
  10. {
  11. /// <summary>
  12. /// Sets a (potentially) private field on the target object.
  13. /// </summary>
  14. /// <param name="obj">the object instance</param>
  15. /// <param name="fieldName">the field to set</param>
  16. /// <param name="value">the value to set it to</param>
  17. public static void SetPrivateField(this object obj, string fieldName, object value)
  18. {
  19. var prop = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
  20. prop.SetValue(obj, value);
  21. }
  22. /// <summary>
  23. /// Gets the value of a (potentially) private field.
  24. /// </summary>
  25. /// <typeparam name="T">the type of te field (result casted)</typeparam>
  26. /// <param name="obj">the object instance to pull from</param>
  27. /// <param name="fieldName">the name of the field to read</param>
  28. /// <returns>the value of the field</returns>
  29. public static T GetPrivateField<T>(this object obj, string fieldName)
  30. {
  31. var prop = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
  32. var value = prop.GetValue(obj);
  33. return (T) value;
  34. }
  35. /// <summary>
  36. /// Sets a (potentially) private propert on the target object.
  37. /// </summary>
  38. /// <param name="obj">the target object instance</param>
  39. /// <param name="propertyName">the name of the property</param>
  40. /// <param name="value">the value to set it to</param>
  41. public static void SetPrivateProperty(this object obj, string propertyName, object value)
  42. {
  43. var prop = obj.GetType()
  44. .GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
  45. prop.SetValue(obj, value, null);
  46. }
  47. /// <summary>
  48. /// Invokes a (potentially) private method.
  49. /// </summary>
  50. /// <param name="obj">the object to call from</param>
  51. /// <param name="methodName">the method name</param>
  52. /// <param name="methodParams">the method parameters</param>
  53. /// <returns>the return value</returns>
  54. public static object InvokePrivateMethod(this object obj, string methodName, params object[] methodParams)
  55. {
  56. MethodInfo dynMethod = obj.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
  57. return dynMethod.Invoke(obj, methodParams);
  58. }
  59. /// <summary>
  60. /// Invokes a (potentially) private method.
  61. /// </summary>
  62. /// <typeparam name="T">the return type</typeparam>
  63. /// <param name="obj">the object to call from</param>
  64. /// <param name="methodName">the method name to call</param>
  65. /// <param name="methodParams">the method's parameters</param>
  66. /// <returns>the return value</returns>
  67. public static T InvokePrivateMethod<T>(this object obj, string methodName, params object[] methodParams)
  68. {
  69. return (T)InvokePrivateMethod(obj, methodName, methodParams);
  70. }
  71. /// <summary>
  72. /// Copies a component of type originalType to a component of overridingType on the destination GameObject.
  73. /// </summary>
  74. /// <param name="original">the original component</param>
  75. /// <param name="originalType">the original component's type</param>
  76. /// <param name="overridingType">the new component's type</param>
  77. /// <param name="destination">the destination GameObject</param>
  78. /// <returns></returns>
  79. public static Component CopyComponent(Component original, Type originalType, Type overridingType, GameObject destination)
  80. {
  81. var copy = destination.AddComponent(overridingType);
  82. Type type = originalType;
  83. while (type != typeof(MonoBehaviour))
  84. {
  85. CopyForType(type, original, copy);
  86. type = type.BaseType;
  87. }
  88. return copy;
  89. }
  90. private static void CopyForType(Type type, Component source, Component destination)
  91. {
  92. FieldInfo[] myObjectFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField);
  93. foreach (FieldInfo fi in myObjectFields)
  94. {
  95. fi.SetValue(destination, fi.GetValue(source));
  96. }
  97. }
  98. }
  99. }