#if !UNITY_EDITOR && UNITY_METRO && !ENABLE_IL2CPP
#define USE_TYPEINFO
#if !UNITY_WINRT_10_0
#define USE_TYPEINFO_EXTENSIONS
#endif
#endif
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
#if USE_TYPEINFO
namespace System {
public static class AssemblyExtensions {
#if USE_TYPEINFO_EXTENSIONS
public static Type[] GetTypes(this Assembly assembly) {
TypeInfo[] infos = assembly.DefinedTypes.ToArray();
Type[] types = new Type[infos.Length];
for (int i = 0; i < infos.Length; ++i) {
types[i] = infos[i].AsType();
}
return types;
}
#endif
public static Type GetType(this Assembly assembly, string name, bool throwOnError) {
var types = assembly.GetTypes();
for (int i = 0; i < types.Length; ++i) {
if (types[i].Name == name) {
return types[i];
}
}
if (throwOnError) throw new Exception("Type " + name + " was not found");
return null;
}
}
}
#endif
namespace FullSerializer.Internal {
///
/// This wraps reflection types so that it is portable across different Unity runtimes.
///
public static class fsPortableReflection {
public static Type[] EmptyTypes = { };
#region Attribute Queries
#if USE_TYPEINFO
public static TAttribute GetAttribute(Type type)
where TAttribute : Attribute {
return GetAttribute(type.GetTypeInfo());
}
public static Attribute GetAttribute(Type type, Type attributeType) {
return GetAttribute(type.GetTypeInfo(), attributeType, /*shouldCache:*/false);
}
public static bool HasAttribute(Type type, Type attributeType) {
return GetAttribute(type, attributeType) != null;
}
#endif
///
/// Returns true if the given attribute is defined on the given element.
///
public static bool HasAttribute(MemberInfo element) {
return HasAttribute(element, typeof(TAttribute));
}
///
/// Returns true if the given attribute is defined on the given element.
///
public static bool HasAttribute(MemberInfo element, bool shouldCache) {
return HasAttribute(element, typeof(TAttribute), shouldCache);
}
///
/// Returns true if the given attribute is defined on the given element.
///
public static bool HasAttribute(MemberInfo element, Type attributeType) {
return HasAttribute(element, attributeType, true);
}
///
/// Returns true if the given attribute is defined on the given element.
///
public static bool HasAttribute(MemberInfo element, Type attributeType, bool shouldCache) {
return element.IsDefined(attributeType, true);
}
///
/// Fetches the given attribute from the given MemberInfo. This method applies caching
/// and is allocation free (after caching has been performed).
///
/// The MemberInfo the get the attribute from.
/// The type of attribute to fetch.
/// The attribute or null.
public static Attribute GetAttribute(MemberInfo element, Type attributeType, bool shouldCache) {
var query = new AttributeQuery {
MemberInfo = element,
AttributeType = attributeType
};
Attribute attribute;
if (_cachedAttributeQueries.TryGetValue(query, out attribute) == false) {
var attributes = element.GetCustomAttributes(attributeType, /*inherit:*/ true);
if (attributes.Length > 0)
attribute = (Attribute)attributes[0];
if (shouldCache)
_cachedAttributeQueries[query] = attribute;
}
return attribute;
}
///
/// Fetches the given attribute from the given MemberInfo.
///
/// The type of attribute to fetch.
/// The MemberInfo to get the attribute from.
/// Should this computation be cached? If this is the only time it will ever be done, don't bother caching.
/// The attribute or null.
public static TAttribute GetAttribute(MemberInfo element, bool shouldCache)
where TAttribute : Attribute {
return (TAttribute)GetAttribute(element, typeof(TAttribute), shouldCache);
}
public static TAttribute GetAttribute(MemberInfo element)
where TAttribute : Attribute {
return GetAttribute(element, /*shouldCache:*/true);
}
private struct AttributeQuery {
public MemberInfo MemberInfo;
public Type AttributeType;
}
private static IDictionary _cachedAttributeQueries =
new Dictionary(new AttributeQueryComparator());
private class AttributeQueryComparator : IEqualityComparer {
public bool Equals(AttributeQuery x, AttributeQuery y) {
return
x.MemberInfo == y.MemberInfo &&
x.AttributeType == y.AttributeType;
}
public int GetHashCode(AttributeQuery obj) {
return
obj.MemberInfo.GetHashCode() +
(17 * obj.AttributeType.GetHashCode());
}
}
#endregion
#if !USE_TYPEINFO
private static BindingFlags DeclaredFlags =
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.DeclaredOnly;
#endif
public static PropertyInfo GetDeclaredProperty(this Type type, string propertyName) {
var props = GetDeclaredProperties(type);
for (int i = 0; i < props.Length; ++i) {
if (props[i].Name == propertyName) {
return props[i];
}
}
return null;
}
public static MethodInfo GetDeclaredMethod(this Type type, string methodName) {
var methods = GetDeclaredMethods(type);
for (int i = 0; i < methods.Length; ++i) {
if (methods[i].Name == methodName) {
return methods[i];
}
}
return null;
}
public static ConstructorInfo GetDeclaredConstructor(this Type type, Type[] parameters) {
var ctors = GetDeclaredConstructors(type);
for (int i = 0; i < ctors.Length; ++i) {
var ctor = ctors[i];
var ctorParams = ctor.GetParameters();
if (parameters.Length != ctorParams.Length) continue;
for (int j = 0; j < ctorParams.Length; ++j) {
// require an exact match
if (ctorParams[j].ParameterType != parameters[j]) continue;
}
return ctor;
}
return null;
}
public static ConstructorInfo[] GetDeclaredConstructors(this Type type) {
#if USE_TYPEINFO
return type.GetTypeInfo().DeclaredConstructors.ToArray();
#else
return type.GetConstructors(DeclaredFlags);
#endif
}
public static MemberInfo[] GetFlattenedMember(this Type type, string memberName) {
var result = new List();
while (type != null) {
var members = GetDeclaredMembers(type);
for (int i = 0; i < members.Length; ++i) {
if (members[i].Name == memberName) {
result.Add(members[i]);
}
}
type = type.Resolve().BaseType;
}
return result.ToArray();
}
public static MethodInfo GetFlattenedMethod(this Type type, string methodName) {
while (type != null) {
var methods = GetDeclaredMethods(type);
for (int i = 0; i < methods.Length; ++i) {
if (methods[i].Name == methodName) {
return methods[i];
}
}
type = type.Resolve().BaseType;
}
return null;
}
public static IEnumerable GetFlattenedMethods(this Type type, string methodName) {
while (type != null) {
var methods = GetDeclaredMethods(type);
for (int i = 0; i < methods.Length; ++i) {
if (methods[i].Name == methodName) {
yield return methods[i];
}
}
type = type.Resolve().BaseType;
}
}
public static PropertyInfo GetFlattenedProperty(this Type type, string propertyName) {
while (type != null) {
var properties = GetDeclaredProperties(type);
for (int i = 0; i < properties.Length; ++i) {
if (properties[i].Name == propertyName) {
return properties[i];
}
}
type = type.Resolve().BaseType;
}
return null;
}
public static MemberInfo GetDeclaredMember(this Type type, string memberName) {
var members = GetDeclaredMembers(type);
for (int i = 0; i < members.Length; ++i) {
if (members[i].Name == memberName) {
return members[i];
}
}
return null;
}
public static MethodInfo[] GetDeclaredMethods(this Type type) {
#if USE_TYPEINFO
return type.GetTypeInfo().DeclaredMethods.ToArray();
#else
return type.GetMethods(DeclaredFlags);
#endif
}
public static PropertyInfo[] GetDeclaredProperties(this Type type) {
#if USE_TYPEINFO
return type.GetTypeInfo().DeclaredProperties.ToArray();
#else
return type.GetProperties(DeclaredFlags);
#endif
}
public static FieldInfo[] GetDeclaredFields(this Type type) {
#if USE_TYPEINFO
return type.GetTypeInfo().DeclaredFields.ToArray();
#else
return type.GetFields(DeclaredFlags);
#endif
}
public static MemberInfo[] GetDeclaredMembers(this Type type) {
#if USE_TYPEINFO
return type.GetTypeInfo().DeclaredMembers.ToArray();
#else
return type.GetMembers(DeclaredFlags);
#endif
}
public static MemberInfo AsMemberInfo(Type type) {
#if USE_TYPEINFO
return type.GetTypeInfo();
#else
return type;
#endif
}
public static bool IsType(MemberInfo member) {
#if USE_TYPEINFO
return member is TypeInfo;
#else
return member is Type;
#endif
}
public static Type AsType(MemberInfo member) {
#if USE_TYPEINFO
return ((TypeInfo)member).AsType();
#else
return (Type)member;
#endif
}
#if USE_TYPEINFO
public static TypeInfo Resolve(this Type type) {
return type.GetTypeInfo();
}
#else
public static Type Resolve(this Type type) {
return type;
}
#endif
#region Extensions
#if USE_TYPEINFO_EXTENSIONS
public static bool IsAssignableFrom(this Type parent, Type child) {
return parent.GetTypeInfo().IsAssignableFrom(child.GetTypeInfo());
}
public static Type GetElementType(this Type type) {
return type.GetTypeInfo().GetElementType();
}
public static MethodInfo GetSetMethod(this PropertyInfo member, bool nonPublic = false) {
// only public requested but the set method is not public
if (nonPublic == false && member.SetMethod != null && member.SetMethod.IsPublic == false) return null;
return member.SetMethod;
}
public static MethodInfo GetGetMethod(this PropertyInfo member, bool nonPublic = false) {
// only public requested but the set method is not public
if (nonPublic == false && member.GetMethod != null && member.GetMethod.IsPublic == false) return null;
return member.GetMethod;
}
public static MethodInfo GetBaseDefinition(this MethodInfo method) {
return method.GetRuntimeBaseDefinition();
}
public static Type[] GetInterfaces(this Type type) {
return type.GetTypeInfo().ImplementedInterfaces.ToArray();
}
public static Type[] GetGenericArguments(this Type type) {
return type.GetTypeInfo().GenericTypeArguments.ToArray();
}
#endif
#endregion
}
}