using System; using System.Reflection; using UnityEngine; namespace IPA.Utilities { /// /// A utility class providing reflection helper methods. /// public static class ReflectionUtil { /// /// Sets a field on the target object. /// /// the object instance /// the field to set /// the value to set it to /// if does not exist on the runtime type of public static void SetField(this object obj, string fieldName, object value) { var prop = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (prop == null) throw new ArgumentException($"Field {fieldName} does not exist", nameof(fieldName)); prop?.SetValue(obj, value); } /// /// Sets a field on the target object, as gotten from . /// /// the type to get the field from /// the object instance /// the field to set /// the value to set it to /// if does not exist on public static void SetField(this T obj, string fieldName, object value) { var prop = typeof(T).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (prop == null) throw new ArgumentException($"Field {fieldName} does not exist", nameof(fieldName)); prop?.SetValue(obj, value); } /// /// Gets the value of a field. /// /// the type of the field (result casted) /// the object instance to pull from /// the name of the field to read /// the value of the field /// if does not exist on the runtime type of public static T GetField(this object obj, string fieldName) { var prop = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); if (prop == null) throw new ArgumentException($"Field {fieldName} does not exist", nameof(fieldName)); var value = prop?.GetValue(obj); return (T) value; } /// /// Gets the value of a field. /// /// the type of the field (result casted) /// the type to get the field from /// the object instance to pull from /// the name of the field to read /// the value of the field /// if does not exist on public static T GetField(this U obj, string fieldName) { var prop = typeof(U).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); if (prop == null) throw new ArgumentException($"Field {fieldName} does not exist", nameof(fieldName)); var value = prop?.GetValue(obj); return (T)value; } /// /// Sets a property on the target object. /// /// the target object instance /// the name of the property /// the value to set it to /// if does not exist on the runtime type of public static void SetProperty(this object obj, string propertyName, object value) { var prop = obj.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (prop == null) throw new ArgumentException($"Property {propertyName} does not exist", nameof(propertyName)); prop?.SetValue(obj, value, null); } /// /// Sets a property on the target object, as gotten from /// /// the type to get the property from /// the object instance /// the property to set /// the value to set it to /// if does not exist on public static void SetProperty(this T obj, string propertyName, object value) { var prop = typeof(T).GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (prop == null) throw new ArgumentException($"Property {propertyName} does not exist", nameof(propertyName)); prop?.SetValue(obj, value, null); } /// /// Invokes a method on an object. /// /// the object to call from /// the method name /// the method arguments /// the return value /// if does not exist on the runtime type of public static object InvokeMethod(this object obj, string methodName, params object[] methodArgs) { MethodInfo dynMethod = obj.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (dynMethod == null) throw new ArgumentException($"Method {methodName} does not exist", nameof(methodName)); return dynMethod?.Invoke(obj, methodArgs); } /// /// Invokes a method from on an object. /// /// the type to search for the method on /// the object instance /// the method's name /// the method arguments /// the return value /// if does not exist on public static object InvokeMethod(this T obj, string methodName, params object[] args) { var dynMethod = typeof(T).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (dynMethod == null) throw new ArgumentException($"Method {methodName} does not exist", nameof(methodName)); return dynMethod?.Invoke(obj, args); } /// /// Invokes a method. /// /// the return type /// the object instance /// the method name to call /// the method's arguments /// the return value /// if does not exist on the runtime type of /// public static T InvokeMethod(this object obj, string methodName, params object[] methodArgs) => (T)InvokeMethod(obj, methodName, methodArgs); /// /// Invokes a method from on an object. /// /// the return type /// the type to search for the method on /// the object instance /// the method name to call /// the method's arguments /// the return value /// if does not exist on /// public static T InvokeMethod(this U obj, string methodName, params object[] methodArgs) => (T)InvokeMethod(obj, methodName, methodArgs); /// /// Copies a component to a component of on the destination . /// /// the original component /// the new component's type /// the destination GameObject /// overrides the source component type (for example, to a superclass) /// the copied component public static Component CopyComponent(this Component original, Type overridingType, GameObject destination, Type originalTypeOverride = null) { var copy = destination.AddComponent(overridingType); var originalType = originalTypeOverride ?? original.GetType(); Type type = originalType; while (type != typeof(MonoBehaviour)) { CopyForType(type, original, copy); type = type?.BaseType; } return copy; } /// /// A generic version of . /// /// /// the overriding type /// the original component /// the destination game object /// overrides the source component type (for example, to a superclass) /// the copied component public static T CopyComponent(this Component original, GameObject destination, Type originalTypeOverride = null) where T : Component { var copy = destination.AddComponent(); var originalType = originalTypeOverride ?? original.GetType(); Type type = originalType; while (type != typeof(MonoBehaviour)) { CopyForType(type, original, copy); type = type?.BaseType; } return copy; } private static void CopyForType(Type type, Component source, Component destination) { FieldInfo[] myObjectFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo fi in myObjectFields) { fi.SetValue(destination, fi.GetValue(source)); } } } }