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.
597 lines
18 KiB
597 lines
18 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Reflection; |
|
using System.Globalization; |
|
|
|
namespace MarkerMetro.Unity.WinLegacy.Reflection |
|
{ |
|
[Flags] |
|
public enum BindingFlags |
|
{ |
|
Default, |
|
Public, |
|
Instance, |
|
InvokeMethod, |
|
NonPublic, |
|
Static, |
|
FlattenHierarchy, |
|
DeclaredOnly, |
|
IgnoreCase |
|
} |
|
|
|
public enum TypeCode |
|
{ |
|
Byte, |
|
Int16, |
|
Int32, |
|
Int64, |
|
SByte, |
|
UInt16, |
|
UInt32, |
|
UInt64, |
|
Single, |
|
Double, |
|
Char, |
|
Boolean, |
|
String, |
|
DateTime, |
|
Decimal, |
|
Empty, |
|
DBNull, // Never used |
|
Object |
|
} |
|
|
|
public static class ReflectionExtensions |
|
{ |
|
|
|
private static readonly Dictionary<Type, TypeCode> _typeCodeTable = |
|
new Dictionary<Type, TypeCode>() |
|
{ |
|
{ typeof( Boolean ), TypeCode.Boolean }, |
|
{ typeof( Char ), TypeCode.Char }, |
|
{ typeof( Byte ), TypeCode.Byte }, |
|
{ typeof( Int16 ), TypeCode.Int16 }, |
|
{ typeof( Int32 ), TypeCode.Int32 }, |
|
{ typeof( Int64 ), TypeCode.Int64 }, |
|
{ typeof( SByte ), TypeCode.SByte }, |
|
{ typeof( UInt16 ), TypeCode.UInt16 }, |
|
{ typeof( UInt32 ), TypeCode.UInt32 }, |
|
{ typeof( UInt64 ), TypeCode.UInt64 }, |
|
{ typeof( Single ), TypeCode.Single }, |
|
{ typeof( Double ), TypeCode.Double }, |
|
{ typeof( DateTime ), TypeCode.DateTime }, |
|
{ typeof( Decimal ), TypeCode.Decimal }, |
|
{ typeof( String ), TypeCode.String }, |
|
}; |
|
|
|
|
|
public static bool IsValueType(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsValueType; |
|
#else |
|
return type.IsValueType; |
|
#endif |
|
} |
|
|
|
public static bool IsGenericType(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsGenericType; |
|
#else |
|
return type.IsGenericType; |
|
#endif |
|
} |
|
|
|
public static object[] GetCustomAttributes(this Type type, bool inherit) |
|
{ |
|
#if NETFX_CORE |
|
var customAttributes = type.GetTypeInfo().GetCustomAttributes(inherit); |
|
if (customAttributes == null) return null; |
|
return customAttributes.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static object[] GetCustomAttributes(this Type type, Type attrType) |
|
{ |
|
#if NETFX_CORE |
|
var customAttributes = type.GetTypeInfo().GetCustomAttributes(attrType); |
|
if (customAttributes == null) return null; |
|
return customAttributes.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static object[] GetCustomAttributes(this Type type, Type attrType, bool inherit) |
|
{ |
|
|
|
#if NETFX_CORE |
|
var customAttributes = type.GetTypeInfo().GetCustomAttributes(attrType, inherit); |
|
if (customAttributes == null) return null; |
|
return customAttributes.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static Assembly GetAssembly(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().Assembly; |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static bool IsAbstract(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsAbstract; |
|
#else |
|
return type.IsAbstract; |
|
#endif |
|
} |
|
|
|
public static bool IsDefined(this Type type, Type attributeType) |
|
{ |
|
#if NETFX_CORE |
|
|
|
return type.GetTypeInfo().IsDefined(attributeType); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static bool IsDefined(this Type type, Type attributeType, bool inherit) |
|
{ |
|
#if NETFX_CORE |
|
|
|
return type.GetTypeInfo().IsDefined(attributeType, inherit); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static bool IsClass(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
|
|
return type.GetTypeInfo().IsClass; |
|
#else |
|
return type.IsClass; |
|
#endif |
|
} |
|
|
|
public static bool IsEnum(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsEnum; |
|
#else |
|
return type.IsEnum; |
|
#endif |
|
} |
|
|
|
public static bool IsPublic(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsPublic; |
|
#else |
|
return type.IsPublic; |
|
#endif |
|
} |
|
|
|
public static bool IsVisible(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsVisible; |
|
#else |
|
return type.IsVisible; |
|
#endif |
|
} |
|
|
|
public static ConstructorInfo GetParameterlessConstructor(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().DeclaredConstructors.FirstOrDefault(c => !c.GetParameters().Any()); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static ConstructorInfo[] GetConstructors(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
var decConstructors = type.GetTypeInfo().DeclaredConstructors; |
|
if (decConstructors == null) return null; |
|
return decConstructors.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static Type GetInterface(this Type type, string name) |
|
{ |
|
return GetInterface(type, name, false); |
|
} |
|
|
|
public static Type GetInterface(this Type type, string name, bool ignoreCase) |
|
{ |
|
#if NETFX_CORE |
|
var interfaces = type.GetTypeInfo().ImplementedInterfaces; |
|
|
|
foreach (var interfaceType in interfaces) |
|
{ |
|
/*We must compare against the generic type definition*/ |
|
var t = interfaceType.IsGenericType() ? interfaceType.GetGenericTypeDefinition() : interfaceType; |
|
|
|
if (t.Name.Equals(name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) |
|
return interfaceType; |
|
if (t.FullName.Equals(name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) |
|
return interfaceType; |
|
} |
|
|
|
return null; |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static PropertyInfo[] GetProperties(this Type type) |
|
{ |
|
if (type == null) |
|
throw new NullReferenceException(); |
|
#if NETFX_CORE |
|
var members = type.GetRuntimeProperties(); |
|
return members == null ? null : members.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
/** |
|
* This implementation currently ignores BindingFlags.FlattenHierarchy. |
|
*/ |
|
public static PropertyInfo[] GetProperties(this Type type, BindingFlags flags) |
|
{ |
|
#if NETFX_CORE |
|
var props = type.GetProperties(); |
|
var result = new List<PropertyInfo>(); |
|
foreach (var prop in props) |
|
if (TestBindingFlags(type, prop.GetMethod, flags) || TestBindingFlags(type, prop.SetMethod, flags)) |
|
result.Add(prop); |
|
return result.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
/** |
|
* Attention: This implementation does not throw AmbiguousMatchException when more than one |
|
* property is found with the specified name and matching the specified binding constraints. |
|
* |
|
* This implementation currently ignores BindingFlags.FlattenHierarchy. |
|
*/ |
|
public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingAttr) |
|
{ |
|
#if NETFX_CORE |
|
var props = type.GetProperties(bindingAttr); |
|
if (!props.Any()) return null; |
|
return props.FirstOrDefault(f => bindingAttr.HasFlag(BindingFlags.IgnoreCase) ? |
|
f.Name.ToLower() == name.ToLower() : f.Name == name); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static PropertyInfo GetProperty(this Type type, string name) |
|
{ |
|
var props = type.GetProperties(); |
|
if (!props.Any()) return null; |
|
return props.FirstOrDefault(f => f.Name == name); |
|
} |
|
|
|
public static MethodInfo[] GetMethods(this Type type) |
|
{ |
|
if (type == null) |
|
throw new NullReferenceException(); |
|
#if NETFX_CORE |
|
var members = type.GetRuntimeMethods(); |
|
return members == null ? null : members.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
/** |
|
* This implementation currently ignores BindingFlags.FlattenHierarchy. |
|
*/ |
|
public static MethodInfo[] GetMethods(this Type t, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance) |
|
{ |
|
#if NETFX_CORE |
|
if (!flags.HasFlag(BindingFlags.Instance) && !flags.HasFlag(BindingFlags.Static)) return null; |
|
|
|
var allMethods = t.GetMethods(); |
|
var resultList = new List<MethodInfo>(); |
|
foreach (var method in allMethods) |
|
{ |
|
if (TestBindingFlags(t, method, flags)) |
|
resultList.Add(method); |
|
} |
|
return resultList.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
/** |
|
* Tests the following BindingFlags: |
|
* Public, NonPublic, Static, Instance, DeclaredOnly. |
|
*/ |
|
private static bool TestBindingFlags(Type t, MethodInfo method, BindingFlags flags) |
|
{ |
|
#if NETFX_CORE |
|
var isValid = (flags.HasFlag(BindingFlags.Public) && method.IsPublic) |
|
|| (flags.HasFlag(BindingFlags.NonPublic) && !method.IsPublic); |
|
isValid &= (flags.HasFlag(BindingFlags.Static) && method.IsStatic) || (flags.HasFlag(BindingFlags.Instance) && !method.IsStatic); |
|
if (flags.HasFlag(BindingFlags.DeclaredOnly)) |
|
isValid &= method.DeclaringType == t; |
|
return isValid; |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
public static MemberInfo[] GetMembers(this Type type) |
|
{ |
|
if (type == null) |
|
throw new NullReferenceException(); |
|
#if NETFX_CORE |
|
var ti = type.GetTypeInfo(); |
|
var result = new List<MemberInfo>(); |
|
if (ti.DeclaredMembers != null) |
|
{ |
|
result.AddRange(ti.DeclaredMembers); |
|
} |
|
return result.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static MemberInfo[] GetMembers(this Type t, BindingFlags flags) |
|
{ |
|
#if NETFX_CORE |
|
if (!flags.HasFlag(BindingFlags.Instance) && !flags.HasFlag(BindingFlags.Static)) return null; |
|
return t.GetMembers(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static Object InvokeMember(this Type t, string name, BindingFlags flags, object binder, object target, object[] args) |
|
{ |
|
#if NETFX_CORE |
|
if (binder != null || target != null) |
|
throw new ArgumentException("doesn't support binder or target when invoking"); |
|
// We only support invoking a normal method, not a field/property/other member |
|
var members = t.GetMethods(); |
|
foreach (var m in members) |
|
{ |
|
if (m.Name.Equals(name)) |
|
{ |
|
return m.Invoke(t, args); |
|
} |
|
} |
|
return null; |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static FieldInfo[] GetFields(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
var fields = type.GetRuntimeFields(); |
|
return fields == null ? null : fields.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static FieldInfo[] GetFields(this Type t, BindingFlags flags) |
|
{ |
|
#if NETFX_CORE |
|
if (!flags.HasFlag(BindingFlags.Instance) && !flags.HasFlag(BindingFlags.Static)) |
|
return null; |
|
|
|
var origFields = t.GetFields(); |
|
var results = new List<FieldInfo>(); |
|
foreach (var field in origFields) |
|
{ |
|
var isValid = (flags.HasFlag(BindingFlags.Public) && field.IsPublic) |
|
|| (flags.HasFlag(BindingFlags.NonPublic) && !field.IsPublic); |
|
isValid &= (flags.HasFlag(BindingFlags.Static) && field.IsStatic) || (flags.HasFlag(BindingFlags.Instance) && !field.IsStatic); |
|
if (flags.HasFlag(BindingFlags.DeclaredOnly)) |
|
isValid &= field.DeclaringType == t; |
|
|
|
results.Add(field); |
|
} |
|
return results.ToArray(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static FieldInfo GetField(this Type type, string name) |
|
{ |
|
#if NETFX_CORE |
|
var fields = type.GetFields(); |
|
if (!fields.Any()) return null; |
|
return fields.FirstOrDefault(f => f.Name == name); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static FieldInfo GetField(this Type type, string name, BindingFlags flags) |
|
{ |
|
#if NETFX_CORE |
|
FieldInfo[] fields = type.GetFields(flags); |
|
if (fields != null) |
|
for (int i = 0; i < fields.Length; i++) |
|
if (fields[i].Name.Equals(name)) |
|
return fields[i]; |
|
return null; |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static MethodInfo GetMethod(this Type type, string name) |
|
{ |
|
return GetMethod(type, name, BindingFlags.Default, null); |
|
} |
|
|
|
public static MethodInfo GetMethod(this Type type, string name, Type[] types) |
|
{ |
|
return GetMethod(type, name, BindingFlags.Default, types); |
|
} |
|
|
|
public static MethodInfo GetMethod(this Type t, string name, BindingFlags flags) |
|
{ |
|
return GetMethod(t, name, flags, null); |
|
} |
|
public static Type GetBaseType(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().BaseType; |
|
#endif |
|
throw new NotImplementedException(); |
|
} |
|
|
|
public static MethodInfo GetMethod(Type t, string name, BindingFlags flags, Type[] parameters) |
|
{ |
|
#if NETFX_CORE |
|
var methods = t.GetMethods(); |
|
foreach (var m in methods) |
|
{ |
|
var plist = m.GetParameters(); |
|
bool match = true; |
|
foreach (var param in plist) |
|
{ |
|
bool valid = true; |
|
if (parameters != null) |
|
{ |
|
foreach (var ptype in parameters) |
|
valid &= ptype == param.ParameterType; |
|
} |
|
match &= valid; |
|
} |
|
if (match) |
|
return m; |
|
} |
|
return null; |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static Type[] GetGenericArguments(this Type t) |
|
{ |
|
#if NETFX_CORE |
|
var ti = t.GetTypeInfo(); |
|
return ti.GenericTypeArguments; |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static bool IsAssignableFrom(this Type current, Type toCompare) |
|
{ |
|
#if NETFX_CORE |
|
return current.GetTypeInfo().IsAssignableFrom(toCompare.GetTypeInfo()); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static bool IsInterface(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsInterface; |
|
#else |
|
return type.IsInterface; |
|
#endif |
|
} |
|
|
|
public static bool IsPrimitive(this Type type) |
|
{ |
|
#if NETFX_CORE |
|
return type.GetTypeInfo().IsPrimitive; |
|
#else |
|
return type.IsPrimitive; |
|
#endif |
|
} |
|
|
|
/** |
|
* Missing IsSubclassOf, this works well |
|
*/ |
|
public static bool IsSubclassOf(this Type type, global::System.Type parent) |
|
{ |
|
#if NETFX_CORE |
|
return parent.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static Type[] GetTypes(this Assembly assembly) |
|
{ |
|
#if NETFX_CORE |
|
if (assembly.DefinedTypes == null) return null; |
|
if (assembly.DefinedTypes.Count() == 0) return new Type[0]; |
|
var typeInfos = assembly.DefinedTypes.ToArray(); |
|
Type[] types = new Type[typeInfos.Count()]; |
|
for (var x = 0; x < types.Length; x++) |
|
{ |
|
types[x] = typeInfos[x].AsType(); |
|
} |
|
return types; |
|
|
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static Type GetType(this Assembly assembly) |
|
{ |
|
#if NETFX_CORE |
|
if (assembly.DefinedTypes == null) return null; |
|
return assembly.GetType(); |
|
#else |
|
throw new NotImplementedException(); |
|
#endif |
|
} |
|
|
|
public static TypeCode GetTypeCode(this Type type) |
|
{ |
|
if (type == null) |
|
{ |
|
return TypeCode.Empty; |
|
} |
|
|
|
TypeCode result; |
|
if (!_typeCodeTable.TryGetValue(type, out result)) |
|
{ |
|
result = TypeCode.Object; |
|
} |
|
|
|
return result; |
|
} |
|
|
|
} |
|
|
|
} |