using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
namespace FullscreenEditor {
/// Class containing method extensions for getting private and internal members.
public static class ReflectionUtility {
private static Assembly[] cachedAssemblies;
public const BindingFlags FULL_BINDING = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
/// Find a type by its name.
public static Type FindClass(string name) {
// return typeof(Editor).Assembly.GetType(name, false, true);
var result = FindTypeInAssembly(name, typeof(Editor).Assembly);
if (result != null)
return result;
if (cachedAssemblies == null)
cachedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
for (var i = 0; i < cachedAssemblies.Length; i++) {
result = FindTypeInAssembly(name, cachedAssemblies[i]);
if (result != null)
return result;
}
return result;
}
private static Type FindTypeInAssembly(string name, Assembly assembly) {
return assembly == null ?
null :
assembly.GetType(name, false, true);
}
/// Find a field of a type by its name.
public static FieldInfo FindField(this Type type, string fieldName, bool throwNotFound = true) {
if (type == null)
throw new ArgumentNullException("type");
var field = type.GetField(fieldName, FULL_BINDING);
if (field == null && throwNotFound)
throw new MissingFieldException(type.FullName, fieldName);
return field;
}
/// Find a property of a type by its name.
public static PropertyInfo FindProperty(this Type type, string propertyName, bool throwNotFound = true) {
if (type == null)
throw new ArgumentNullException("type");
var prop = type.GetProperty(propertyName, FULL_BINDING);
if (prop == null && throwNotFound)
throw new MissingMemberException(type.FullName, propertyName);
return prop;
}
/// Find a method of a type by its name.
public static MethodInfo FindMethod(this Type type, string methodName, Type[] args = null, bool throwNotFound = true) {
if (type == null)
throw new ArgumentNullException("type");
MethodInfo method;
if (args == null) {
method = type.GetMethod(methodName, FULL_BINDING);
// method = type.GetMethods(FULL_BINDING)
// .Where(m => m.Name == methodName)
// .FirstOrDefault();
} else {
method = type.GetMethod(methodName, FULL_BINDING, null, args, null);
// There are very specific cases where the above method may not bind properly
// e.g. when the method declares an enum and the arg type is an int, so we ignore the args
// and hope that there are no ambiguity of methods
if (method == null) {
method = FindMethod(type, methodName, null, throwNotFound);
if (method != null && method.GetParameters().Length != args.Length)
method = null;
}
}
if (method == null && throwNotFound)
throw new MissingMethodException(type.FullName, methodName);
return method;
}
/// Get the value of the static field.
public static T GetFieldValue(this Type type, string fieldName) { return (T)type.FindField(fieldName).GetValue(null); }
/// Get the value of the instance field.
public static T GetFieldValue(this object obj, string fieldName) { return (T)obj.GetType().FindField(fieldName).GetValue(obj); }
/// Set the value of the static field.
public static void SetFieldValue(this Type type, string fieldName, object value) { type.FindField(fieldName).SetValue(null, value); }
/// Set the value of the instance field.
public static void SetFieldValue(this object obj, string fieldName, object value) { obj.GetType().FindField(fieldName).SetValue(obj, value); }
/// Get the value of the static property.
public static T GetPropertyValue(this Type type, string propertyName) { return (T)type.FindProperty(propertyName).GetValue(null, null); }
/// Get the value of the instance property.
public static T GetPropertyValue(this object obj, string propertyName) { return (T)obj.GetType().FindProperty(propertyName).GetValue(obj, null); }
/// Set the value of the static property.
public static void SetPropertyValue(this Type type, string propertyName, object value) { type.FindProperty(propertyName).SetValue(null, value, null); }
/// Set the value of the instance property.
public static void SetPropertyValue(this object obj, string propertyName, object value) { obj.GetType().FindProperty(propertyName).SetValue(obj, value, null); }
/// Invoke a static method on the type and return the result.
public static T InvokeMethod(this Type type, string methodName, params object[] args) { return (T)type.FindMethod(methodName, args.Select(a => a.GetType()).ToArray()).Invoke(null, args); }
/// Invoke a method on the object instance and return the result.
public static T InvokeMethod(this object obj, string methodName, params object[] args) { return (T)obj.GetType().FindMethod(methodName, args.Select(a => a.GetType()).ToArray()).Invoke(obj, args); }
/// Invoke a static method on the type.
public static void InvokeMethod(this Type type, string methodName, params object[] args) { type.FindMethod(methodName, args.Select(a => a.GetType()).ToArray()).Invoke(null, args); }
/// Invoke a method on the object instance.
public static void InvokeMethod(this object obj, string methodName, params object[] args) { obj.GetType().FindMethod(methodName, args.Select(a => a.GetType()).ToArray()).Invoke(obj, args); }
/// Returns wheter the given type is the same as another one.
/// Type that will be checked.
/// Type to check against.
/// Returns true if the checked type is inherited from the type argument.
public static bool IsOfType(this Type toCheck, Type type, bool orInherited = true) {
return type == toCheck || (orInherited && type.IsAssignableFrom(toCheck));
}
/// Returns wheter the given instance is of a given type.
/// The instance to check.
/// Type to check against.
/// Returns true if the instance is inherited from the type argument.
public static bool IsOfType(this T obj, Type type, bool orInherited = true) {
return obj.GetType().IsOfType(type, orInherited);
}
/// Throws an exception if the instance is not of the given type.
/// The instance to check.
/// Type to check against.
/// Do not throw if the instance is inherited from the type argument.
public static void EnsureOfType(this T obj, Type type, bool orInherited = true) {
if (!obj.IsOfType(type, orInherited))
throw new InvalidCastException(
string.Format("Object {0} must be of type {1}{2}",
obj.GetType().FullName,
type.FullName,
orInherited? " or inherited from it": ""
)
);
}
/// Returns whether the type defines the static field.
public static bool HasField(this Type type, string fieldName) {
return type.FindField(fieldName, false) != null;
}
/// Returns whether the type defines the static property.
public static bool HasProperty(this Type type, string propertyName) {
return type.FindProperty(propertyName, false) != null;
}
/// Returns whether the type defines the static method.
public static bool HasMethod(this Type type, string methodName, Type[] args = null) {
return type.FindMethod(methodName, args, false) != null;
}
/// Returns whether the object type defines the instance field.
public static bool HasField(this object obj, string fieldName) {
return obj.GetType().HasField(fieldName);
}
/// Returns whether the object type defines the instance property.
public static bool HasProperty(this object obj, string propertyName) {
return obj.GetType().HasProperty(propertyName);
}
/// Returns whether the object type defines the instance method.
public static bool HasMethod(this object obj, string methodName, Type[] args = null) {
return obj.GetType().HasMethod(methodName, args);
}
}
}