ReflectionUtils
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Text;
namespace Newtonsoft.Json.Utilities
{
internal static class ReflectionUtils
{
public static readonly Type[] EmptyTypes;
static ReflectionUtils()
{
EmptyTypes = Type.EmptyTypes;
}
public static bool IsVirtual(this PropertyInfo propertyInfo)
{
ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
MethodInfo getMethod = propertyInfo.GetGetMethod();
if (getMethod != (MethodInfo)null && getMethod.IsVirtual)
return true;
getMethod = propertyInfo.GetSetMethod();
if (getMethod != (MethodInfo)null && getMethod.IsVirtual)
return true;
return false;
}
public static MethodInfo GetBaseDefinition(this PropertyInfo propertyInfo)
{
ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
MethodInfo getMethod = propertyInfo.GetGetMethod();
if (getMethod != (MethodInfo)null)
return getMethod.GetBaseDefinition();
getMethod = propertyInfo.GetSetMethod();
if (getMethod != (MethodInfo)null)
return getMethod.GetBaseDefinition();
return null;
}
public static bool IsPublic(PropertyInfo property)
{
if (property.GetGetMethod() != (MethodInfo)null && property.GetGetMethod().IsPublic)
return true;
if (property.GetSetMethod() != (MethodInfo)null && property.GetSetMethod().IsPublic)
return true;
return false;
}
public static Type GetObjectType(object v)
{
return v?.GetType();
}
public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat, SerializationBinder binder)
{
string text;
if (binder != null) {
binder.BindToName(t, out string assemblyName, out string typeName);
text = typeName + ((assemblyName == null) ? "" : (", " + assemblyName));
} else
text = t.AssemblyQualifiedName;
switch (assemblyFormat) {
case FormatterAssemblyStyle.Simple:
return RemoveAssemblyDetails(text);
case FormatterAssemblyStyle.Full:
return text;
default:
throw new ArgumentOutOfRangeException();
}
}
private static string RemoveAssemblyDetails(string fullyQualifiedTypeName)
{
StringBuilder stringBuilder = new StringBuilder();
bool flag = false;
bool flag2 = false;
foreach (char c in fullyQualifiedTypeName) {
switch (c) {
case '[':
flag = false;
flag2 = false;
stringBuilder.Append(c);
break;
case ']':
flag = false;
flag2 = false;
stringBuilder.Append(c);
break;
case ',':
if (!flag) {
flag = true;
stringBuilder.Append(c);
} else
flag2 = true;
break;
default:
if (!flag2)
stringBuilder.Append(c);
break;
}
}
return stringBuilder.ToString();
}
public static bool HasDefaultConstructor(Type t, bool nonPublic)
{
ValidationUtils.ArgumentNotNull(t, "t");
if (t.IsValueType())
return true;
return GetDefaultConstructor(t, nonPublic) != (ConstructorInfo)null;
}
public static ConstructorInfo GetDefaultConstructor(Type t)
{
return GetDefaultConstructor(t, false);
}
public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic)
{
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
if (nonPublic)
bindingFlags |= BindingFlags.NonPublic;
return t.GetConstructors(bindingFlags).SingleOrDefault((ConstructorInfo c) => !c.GetParameters().Any());
}
public static bool IsNullable(Type t)
{
ValidationUtils.ArgumentNotNull(t, "t");
if (t.IsValueType())
return IsNullableType(t);
return true;
}
public static bool IsNullableType(Type t)
{
ValidationUtils.ArgumentNotNull(t, "t");
if (t.IsGenericType())
return t.GetGenericTypeDefinition() == typeof(Nullable<>);
return false;
}
public static Type EnsureNotNullableType(Type t)
{
if (!IsNullableType(t))
return t;
return Nullable.GetUnderlyingType(t);
}
public static bool IsGenericDefinition(Type type, Type genericInterfaceDefinition)
{
if (!type.IsGenericType())
return false;
Type genericTypeDefinition = type.GetGenericTypeDefinition();
return genericTypeDefinition == genericInterfaceDefinition;
}
public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition)
{
Type implementingType;
return ImplementsGenericDefinition(type, genericInterfaceDefinition, out implementingType);
}
public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, out Type implementingType)
{
ValidationUtils.ArgumentNotNull(type, "type");
ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, "genericInterfaceDefinition");
if (!genericInterfaceDefinition.IsInterface() || !genericInterfaceDefinition.IsGenericTypeDefinition())
throw new ArgumentNullException("'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition));
if (type.IsInterface() && type.IsGenericType()) {
Type genericTypeDefinition = type.GetGenericTypeDefinition();
if (genericInterfaceDefinition == genericTypeDefinition) {
implementingType = type;
return true;
}
}
Type[] interfaces = type.GetInterfaces();
foreach (Type type2 in interfaces) {
if (type2.IsGenericType()) {
Type genericTypeDefinition2 = type2.GetGenericTypeDefinition();
if (genericInterfaceDefinition == genericTypeDefinition2) {
implementingType = type2;
return true;
}
}
}
implementingType = null;
return false;
}
public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition)
{
Type implementingType;
return InheritsGenericDefinition(type, genericClassDefinition, out implementingType);
}
public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type implementingType)
{
ValidationUtils.ArgumentNotNull(type, "type");
ValidationUtils.ArgumentNotNull(genericClassDefinition, "genericClassDefinition");
if (!genericClassDefinition.IsClass() || !genericClassDefinition.IsGenericTypeDefinition())
throw new ArgumentNullException("'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition));
return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType);
}
private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type implementingType)
{
if (currentType.IsGenericType()) {
Type genericTypeDefinition = currentType.GetGenericTypeDefinition();
if (genericClassDefinition == genericTypeDefinition) {
implementingType = currentType;
return true;
}
}
if (currentType.BaseType() == (Type)null) {
implementingType = null;
return false;
}
return InheritsGenericDefinitionInternal(currentType.BaseType(), genericClassDefinition, out implementingType);
}
public static Type GetCollectionItemType(Type type)
{
ValidationUtils.ArgumentNotNull(type, "type");
if (type.IsArray)
return type.GetElementType();
if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out Type implementingType)) {
if (implementingType.IsGenericTypeDefinition())
throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
return implementingType.GetGenericArguments()[0];
}
if (typeof(IEnumerable).IsAssignableFrom(type))
return null;
throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
}
public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
{
ValidationUtils.ArgumentNotNull(dictionaryType, "type");
if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<, >), out Type implementingType)) {
if (implementingType.IsGenericTypeDefinition())
throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
Type[] genericArguments = implementingType.GetGenericArguments();
keyType = genericArguments[0];
valueType = genericArguments[1];
} else {
if (!typeof(IDictionary).IsAssignableFrom(dictionaryType))
throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
keyType = null;
valueType = null;
}
}
public static Type GetMemberUnderlyingType(MemberInfo member)
{
ValidationUtils.ArgumentNotNull(member, "member");
switch (member.MemberType()) {
case MemberTypes.Field:
return ((FieldInfo)member).FieldType;
case MemberTypes.Property:
return ((PropertyInfo)member).PropertyType;
case MemberTypes.Event:
return ((EventInfo)member).EventHandlerType;
default:
throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or EventInfo", "member");
}
}
public static bool IsIndexedProperty(MemberInfo member)
{
ValidationUtils.ArgumentNotNull(member, "member");
PropertyInfo propertyInfo = member as PropertyInfo;
if (propertyInfo != (PropertyInfo)null)
return IsIndexedProperty(propertyInfo);
return false;
}
public static bool IsIndexedProperty(PropertyInfo property)
{
ValidationUtils.ArgumentNotNull(property, "property");
return property.GetIndexParameters().Length > 0;
}
public static object GetMemberValue(MemberInfo member, object target)
{
ValidationUtils.ArgumentNotNull(member, "member");
ValidationUtils.ArgumentNotNull(target, "target");
switch (member.MemberType()) {
case MemberTypes.Field:
return ((FieldInfo)member).GetValue(target);
case MemberTypes.Property:
try {
return ((PropertyInfo)member).GetValue(target, null);
} catch (TargetParameterCountException innerException) {
throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), innerException);
}
default:
throw new ArgumentException("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, CultureInfo.InvariantCulture, member.Name), "member");
}
}
public static void SetMemberValue(MemberInfo member, object target, object value)
{
ValidationUtils.ArgumentNotNull(member, "member");
ValidationUtils.ArgumentNotNull(target, "target");
switch (member.MemberType()) {
case MemberTypes.Field:
((FieldInfo)member).SetValue(target, value);
break;
case MemberTypes.Property:
((PropertyInfo)member).SetValue(target, value, null);
break;
default:
throw new ArgumentException("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member");
}
}
public static bool CanReadMemberValue(MemberInfo member, bool nonPublic)
{
switch (member.MemberType()) {
case MemberTypes.Field: {
FieldInfo fieldInfo = (FieldInfo)member;
if (nonPublic)
return true;
if (fieldInfo.IsPublic)
return true;
return false;
}
case MemberTypes.Property: {
PropertyInfo propertyInfo = (PropertyInfo)member;
if (!propertyInfo.CanRead)
return false;
if (nonPublic)
return true;
return propertyInfo.GetGetMethod(nonPublic) != (MethodInfo)null;
}
default:
return false;
}
}
public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly)
{
switch (member.MemberType()) {
case MemberTypes.Field: {
FieldInfo fieldInfo = (FieldInfo)member;
if (fieldInfo.IsInitOnly && !canSetReadOnly)
return false;
if (nonPublic)
return true;
if (fieldInfo.IsPublic)
return true;
return false;
}
case MemberTypes.Property: {
PropertyInfo propertyInfo = (PropertyInfo)member;
if (!propertyInfo.CanWrite)
return false;
if (nonPublic)
return true;
return propertyInfo.GetSetMethod(nonPublic) != (MethodInfo)null;
}
default:
return false;
}
}
public static List<MemberInfo> GetFieldsAndProperties(Type type, BindingFlags bindingAttr)
{
List<MemberInfo> list = new List<MemberInfo>();
list.AddRange(GetFields(type, bindingAttr));
list.AddRange(GetProperties(type, bindingAttr));
List<MemberInfo> list2 = new List<MemberInfo>(list.Count);
foreach (IGrouping<string, MemberInfo> item in from m in list
group m by m.Name) {
int num = item.Count();
IList<MemberInfo> source = item.ToList();
if (num == 1)
list2.Add(source.First());
else {
IEnumerable<MemberInfo> collection = source.Where(delegate(MemberInfo m) {
if (IsOverridenGenericMember(m, bindingAttr))
return m.Name == "Item";
return true;
});
list2.AddRange(collection);
}
}
return list2;
}
private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr)
{
MemberTypes memberTypes = memberInfo.MemberType();
if (memberTypes != MemberTypes.Field && memberTypes != MemberTypes.Property)
throw new ArgumentException("Member must be a field or property.");
Type declaringType = memberInfo.DeclaringType;
if (!declaringType.IsGenericType())
return false;
Type genericTypeDefinition = declaringType.GetGenericTypeDefinition();
if (genericTypeDefinition == (Type)null)
return false;
MemberInfo[] member = genericTypeDefinition.GetMember(memberInfo.Name, bindingAttr);
if (member.Length == 0)
return false;
Type memberUnderlyingType = GetMemberUnderlyingType(member[0]);
if (!memberUnderlyingType.IsGenericParameter)
return false;
return true;
}
public static T GetAttribute<T>(object attributeProvider) where T : Attribute
{
return GetAttribute<T>(attributeProvider, true);
}
public static T GetAttribute<T>(object attributeProvider, bool inherit) where T : Attribute
{
T[] attributes = GetAttributes<T>(attributeProvider, inherit);
if (attributes == null)
return null;
return attributes.SingleOrDefault();
}
public static T[] GetAttributes<T>(object attributeProvider, bool inherit) where T : Attribute
{
ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider");
if (attributeProvider is Type)
return (T[])((Type)attributeProvider).GetCustomAttributes(typeof(T), inherit);
if (attributeProvider is Assembly)
return (T[])Attribute.GetCustomAttributes((Assembly)attributeProvider, typeof(T));
if (attributeProvider is MemberInfo)
return (T[])Attribute.GetCustomAttributes((MemberInfo)attributeProvider, typeof(T), inherit);
if (attributeProvider is Module)
return (T[])Attribute.GetCustomAttributes((Module)attributeProvider, typeof(T), inherit);
if (attributeProvider is ParameterInfo)
return (T[])Attribute.GetCustomAttributes((ParameterInfo)attributeProvider, typeof(T), inherit);
return (T[])((ICustomAttributeProvider)attributeProvider).GetCustomAttributes(typeof(T), inherit);
}
public static void SplitFullyQualifiedTypeName(string fullyQualifiedTypeName, out string typeName, out string assemblyName)
{
int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);
if (assemblyDelimiterIndex.HasValue) {
typeName = fullyQualifiedTypeName.Substring(0, assemblyDelimiterIndex.Value).Trim();
assemblyName = fullyQualifiedTypeName.Substring(assemblyDelimiterIndex.Value + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.Value - 1).Trim();
} else {
typeName = fullyQualifiedTypeName;
assemblyName = null;
}
}
private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName)
{
int num = 0;
for (int i = 0; i < fullyQualifiedTypeName.Length; i++) {
switch (fullyQualifiedTypeName[i]) {
case '[':
num++;
break;
case ']':
num--;
break;
case ',':
if (num == 0)
return i;
break;
}
}
return null;
}
public static MemberInfo GetMemberInfoFromType(Type targetType, MemberInfo memberInfo)
{
MemberTypes memberTypes = memberInfo.MemberType();
if (memberTypes == MemberTypes.Property) {
PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
Type[] types = (from p in propertyInfo.GetIndexParameters()
select p.ParameterType).ToArray();
return targetType.GetProperty(propertyInfo.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, propertyInfo.PropertyType, types, null);
}
return targetType.GetMember(memberInfo.Name, memberInfo.MemberType(), BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault();
}
public static IEnumerable<FieldInfo> GetFields(Type targetType, BindingFlags bindingAttr)
{
ValidationUtils.ArgumentNotNull(targetType, "targetType");
List<MemberInfo> list = new List<MemberInfo>(targetType.GetFields(bindingAttr));
GetChildPrivateFields(list, targetType, bindingAttr);
return list.Cast<FieldInfo>();
}
private static void GetChildPrivateFields(IList<MemberInfo> initialFields, Type targetType, BindingFlags bindingAttr)
{
if ((bindingAttr & BindingFlags.NonPublic) != 0) {
BindingFlags bindingAttr2 = bindingAttr.RemoveFlag(BindingFlags.Public);
while ((targetType = targetType.BaseType()) != (Type)null) {
IEnumerable<MemberInfo> collection = (from f in targetType.GetFields(bindingAttr2)
where f.IsPrivate
select f).Cast<MemberInfo>();
initialFields.AddRange(collection);
}
}
}
public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
{
ValidationUtils.ArgumentNotNull(targetType, "targetType");
List<PropertyInfo> list = new List<PropertyInfo>(targetType.GetProperties(bindingAttr));
GetChildPrivateProperties(list, targetType, bindingAttr);
for (int i = 0; i < list.Count; i++) {
PropertyInfo propertyInfo = list[i];
if (propertyInfo.DeclaringType != targetType) {
PropertyInfo propertyInfo3 = list[i] = (PropertyInfo)GetMemberInfoFromType(propertyInfo.DeclaringType, propertyInfo);
}
}
return list;
}
public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag)
{
if ((bindingAttr & flag) != flag)
return bindingAttr;
return bindingAttr ^ flag;
}
private static void GetChildPrivateProperties(IList<PropertyInfo> initialProperties, Type targetType, BindingFlags bindingAttr)
{
while ((targetType = targetType.BaseType()) != (Type)null) {
PropertyInfo[] properties = targetType.GetProperties(bindingAttr);
foreach (PropertyInfo propertyInfo in properties) {
PropertyInfo subTypeProperty = propertyInfo;
if (!IsPublic(subTypeProperty)) {
int num = initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name);
if (num == -1)
initialProperties.Add(subTypeProperty);
else
initialProperties[num] = subTypeProperty;
} else if (!subTypeProperty.IsVirtual()) {
int num2 = initialProperties.IndexOf(delegate(PropertyInfo p) {
if (p.Name == subTypeProperty.Name)
return p.DeclaringType == subTypeProperty.DeclaringType;
return false;
});
if (num2 == -1)
initialProperties.Add(subTypeProperty);
} else {
int num3 = initialProperties.IndexOf(delegate(PropertyInfo p) {
if (p.Name == subTypeProperty.Name && p.IsVirtual() && p.GetBaseDefinition() != (MethodInfo)null)
return p.GetBaseDefinition().DeclaringType.IsAssignableFrom(subTypeProperty.DeclaringType);
return false;
});
if (num3 == -1)
initialProperties.Add(subTypeProperty);
}
}
}
}
public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method)
{
return currentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(delegate(MethodInfo info) {
if (info.Name == method && info.DeclaringType != methodDeclaringType)
return info.GetBaseDefinition().DeclaringType == methodDeclaringType;
return false;
});
}
public static object GetDefaultValue(Type type)
{
if (type.IsValueType()) {
switch (ConvertUtils.GetTypeCode(type)) {
case PrimitiveTypeCode.Boolean:
return false;
case PrimitiveTypeCode.Char:
case PrimitiveTypeCode.SByte:
case PrimitiveTypeCode.Int16:
case PrimitiveTypeCode.UInt16:
case PrimitiveTypeCode.Int32:
case PrimitiveTypeCode.Byte:
case PrimitiveTypeCode.UInt32:
return 0;
case PrimitiveTypeCode.Int64:
case PrimitiveTypeCode.UInt64:
return 0;
case PrimitiveTypeCode.Single:
return 0;
case PrimitiveTypeCode.Double:
return 0;
case PrimitiveTypeCode.Decimal:
return 0;
case PrimitiveTypeCode.DateTime:
return default(DateTime);
case PrimitiveTypeCode.BigInteger:
return default(BigInteger);
case PrimitiveTypeCode.Guid:
return default(Guid);
case PrimitiveTypeCode.DateTimeOffset:
return default(DateTimeOffset);
default:
if (IsNullable(type))
return null;
return Activator.CreateInstance(type);
}
}
return null;
}
}
}