194 lines
5.4 KiB
C#
194 lines
5.4 KiB
C#
#if UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_4 || UNITY_4_7 || UNITY_5 || UNITY_5_3_OR_NEWER
|
|
#define UNITY
|
|
#endif
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
namespace GameDevWare.Serialization
|
|
{
|
|
internal static class ReflectionExtensions
|
|
{
|
|
private static readonly Dictionary<Type, MethodInfo> GetNameMethods = new Dictionary<Type, MethodInfo>();
|
|
private static readonly object[] EmptyArgs = new object[0];
|
|
|
|
public static bool IsInstantiationOf(this Type type, Type openGenericType)
|
|
{
|
|
if (type == null)
|
|
throw new ArgumentNullException("type");
|
|
if (openGenericType == null)
|
|
throw new ArgumentNullException("openGenericType");
|
|
|
|
if (openGenericType.IsGenericType && !openGenericType.IsGenericTypeDefinition)
|
|
throw new ArgumentException(string.Format("Type should be open generic type '{0}'.", openGenericType));
|
|
|
|
var genericType = type;
|
|
if (type.IsGenericType)
|
|
{
|
|
if (type.IsGenericType && !type.IsGenericTypeDefinition)
|
|
genericType = type.GetGenericTypeDefinition();
|
|
|
|
if (genericType == openGenericType || genericType.IsSubclassOf(openGenericType))
|
|
return true;
|
|
}
|
|
// clean
|
|
genericType = null;
|
|
|
|
// check interfaces
|
|
foreach (var interfc in type.GetInterfaces())
|
|
{
|
|
genericType = interfc;
|
|
|
|
if (!interfc.IsGenericType)
|
|
continue;
|
|
|
|
if (!interfc.IsGenericTypeDefinition)
|
|
genericType = interfc.GetGenericTypeDefinition();
|
|
|
|
if (genericType == openGenericType || genericType.IsSubclassOf(openGenericType))
|
|
return true;
|
|
}
|
|
|
|
if (type.BaseType != null && type.BaseType != typeof (object))
|
|
return IsInstantiationOf(type.BaseType, openGenericType);
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool HasMultipleInstantiations(this Type type, Type openGenericType)
|
|
{
|
|
if (type == null)
|
|
throw new ArgumentNullException("type");
|
|
if (openGenericType == null)
|
|
throw new ArgumentNullException("openGenericType");
|
|
|
|
if (openGenericType.IsGenericType && !openGenericType.IsGenericTypeDefinition)
|
|
throw new ArgumentException(string.Format("Type should be open generic type '{0}'.", openGenericType));
|
|
|
|
// can't has multiple implementations of class
|
|
if (!openGenericType.IsInterface)
|
|
return false;
|
|
|
|
var found = 0;
|
|
|
|
var genericType = type;
|
|
if (type.IsGenericType)
|
|
{
|
|
if (type.IsGenericType && !type.IsGenericTypeDefinition)
|
|
genericType = type.GetGenericTypeDefinition();
|
|
|
|
if (genericType == openGenericType || genericType.IsSubclassOf(openGenericType))
|
|
found++;
|
|
}
|
|
// clean
|
|
genericType = null;
|
|
|
|
// check interfaces
|
|
foreach (var interfc in type.GetInterfaces())
|
|
{
|
|
genericType = interfc;
|
|
|
|
if (!interfc.IsGenericType)
|
|
continue;
|
|
|
|
if (!interfc.IsGenericTypeDefinition)
|
|
genericType = interfc.GetGenericTypeDefinition();
|
|
|
|
if (genericType == openGenericType || genericType.IsSubclassOf(openGenericType))
|
|
found++;
|
|
}
|
|
|
|
|
|
return found > 1;
|
|
}
|
|
|
|
public static Type[] GetInstantiationArguments(this Type type, Type openGenericType)
|
|
{
|
|
if (type == null)
|
|
throw new ArgumentNullException("type");
|
|
if (openGenericType == null)
|
|
throw new ArgumentNullException("openGenericType");
|
|
|
|
if (openGenericType.IsGenericType && !openGenericType.IsGenericTypeDefinition)
|
|
throw new ArgumentException(string.Format("Type should be open generic type '{0}'.", openGenericType));
|
|
|
|
var genericType = type;
|
|
if (type.IsGenericType)
|
|
{
|
|
if (type.IsGenericType && !type.IsGenericTypeDefinition)
|
|
genericType = type.GetGenericTypeDefinition();
|
|
|
|
if (genericType == openGenericType || genericType.IsSubclassOf(openGenericType))
|
|
return type.GetGenericArguments();
|
|
}
|
|
|
|
// clean
|
|
genericType = null;
|
|
|
|
// check interfaces
|
|
foreach (var _interface in type.GetInterfaces())
|
|
{
|
|
genericType = _interface;
|
|
|
|
if (!_interface.IsGenericType)
|
|
continue;
|
|
|
|
if (!_interface.IsGenericTypeDefinition)
|
|
genericType = _interface.GetGenericTypeDefinition();
|
|
|
|
|
|
if (genericType == openGenericType || genericType.IsSubclassOf(openGenericType))
|
|
return _interface.GetGenericArguments();
|
|
}
|
|
|
|
|
|
if (type.BaseType != null && type.BaseType != typeof (object))
|
|
return GetInstantiationArguments(type.BaseType, openGenericType);
|
|
|
|
return null;
|
|
}
|
|
|
|
public static string GetDataMemberName(object dataMemberAttribute)
|
|
{
|
|
if (dataMemberAttribute == null) throw new ArgumentNullException("dataMemberAttribute");
|
|
|
|
var type = dataMemberAttribute.GetType();
|
|
var getName = default(MethodInfo);
|
|
|
|
lock (GetNameMethods)
|
|
{
|
|
if (!GetNameMethods.TryGetValue(type, out getName))
|
|
{
|
|
getName = type.GetMethod("get_Name", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
|
|
|
|
if (getName == null || getName.ReturnType != typeof (string) || getName.GetParameters().Length != 0)
|
|
getName = null;
|
|
|
|
if (getName == null)
|
|
{
|
|
var getNameProperty = type.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public, null, typeof (string),
|
|
Type.EmptyTypes, null);
|
|
if (getNameProperty != null)
|
|
getName = getNameProperty.GetGetMethod(nonPublic: false);
|
|
}
|
|
|
|
GetNameMethods.Add(type, getName);
|
|
}
|
|
}
|
|
|
|
if (getName != null)
|
|
return (string) getName.Invoke(dataMemberAttribute, EmptyArgs);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
#if NET35 || UNITY
|
|
public static Type GetTypeInfo(this Type type)
|
|
{
|
|
return type;
|
|
}
|
|
#endif
|
|
}
|
|
}
|