ReflectionUtils
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities.LinqBridge;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
namespace Newtonsoft.Json.Utilities
{
    [System.Runtime.CompilerServices.NullableContext(1)]
    [System.Runtime.CompilerServices.Nullable(0)]
    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(true);
            if ((object)getMethod != null && getMethod.IsVirtual)
                return true;
            getMethod = propertyInfo.GetSetMethod(true);
            if ((object)getMethod != null && getMethod.IsVirtual)
                return true;
            return false;
        }
        [return: System.Runtime.CompilerServices.Nullable(2)]
        public static MethodInfo GetBaseDefinition(this PropertyInfo propertyInfo)
        {
            ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
            MethodInfo getMethod = propertyInfo.GetGetMethod(true);
            if ((object)getMethod != null)
                return getMethod.GetBaseDefinition();
            return propertyInfo.GetSetMethod(true)?.GetBaseDefinition();
        }
        public static bool IsPublic(PropertyInfo property)
        {
            MethodInfo getMethod = property.GetGetMethod();
            if ((object)getMethod != null && getMethod.IsPublic)
                return true;
            MethodInfo setMethod = property.GetSetMethod();
            if ((object)setMethod != null && setMethod.IsPublic)
                return true;
            return false;
        }
        [System.Runtime.CompilerServices.NullableContext(2)]
        public static Type GetObjectType(object v)
        {
            return v?.GetType();
        }
        public static string GetTypeName(Type t, TypeNameAssemblyFormatHandling assemblyFormat, [System.Runtime.CompilerServices.Nullable(2)] ISerializationBinder binder)
        {
            string fullyQualifiedTypeName = GetFullyQualifiedTypeName(t, binder);
            switch (assemblyFormat) {
            case TypeNameAssemblyFormatHandling.Simple:
                return RemoveAssemblyDetails(fullyQualifiedTypeName);
            case TypeNameAssemblyFormatHandling.Full:
                return fullyQualifiedTypeName;
            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        private static string GetFullyQualifiedTypeName(Type t, [System.Runtime.CompilerServices.Nullable(2)] ISerializationBinder binder)
        {
            if (binder != null) {
                binder.BindToName(t, out string assemblyName, out string typeName);
                if ((assemblyName == null) & (typeName == null))
                    return t.AssemblyQualifiedName;
                return typeName + ((assemblyName == null) ? "" : (", " + assemblyName));
            }
            return t.AssemblyQualifiedName;
        }
        private static string RemoveAssemblyDetails(string fullyQualifiedTypeName)
        {
            StringBuilder stringBuilder = new StringBuilder();
            bool flag = false;
            bool flag2 = false;
            foreach (char c in fullyQualifiedTypeName) {
                switch (c) {
                case '[':
                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 (object)GetDefaultConstructor(t, nonPublic) != 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 (object)t.GetGenericTypeDefinition() == typeof(Nullable<>);
            return false;
        }
        public static Type EnsureNotNullableType(Type t)
        {
            if (!IsNullableType(t))
                return t;
            return Nullable.GetUnderlyingType(t);
        }
        public static Type EnsureNotByRefType(Type t)
        {
            if (!t.IsByRef || !t.HasElementType)
                return t;
            return t.GetElementType();
        }
        public static bool IsGenericDefinition(Type type, Type genericInterfaceDefinition)
        {
            if (!type.IsGenericType())
                return false;
            return (object)type.GetGenericTypeDefinition() == 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, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] 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 ((object)genericInterfaceDefinition == genericTypeDefinition) {
                    implementingType = type;
                    return true;
                }
            }
            Type[] interfaces = type.GetInterfaces();
            foreach (Type type2 in interfaces) {
                if (type2.IsGenericType()) {
                    Type genericTypeDefinition2 = type2.GetGenericTypeDefinition();
                    if ((object)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, [System.Runtime.CompilerServices.Nullable(2)] 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, [System.Runtime.CompilerServices.Nullable(2)] out Type implementingType)
        {
            do {
                if (currentType.IsGenericType() && (object)genericClassDefinition == currentType.GetGenericTypeDefinition()) {
                    implementingType = currentType;
                    return true;
                }
                currentType = currentType.BaseType();
            } while ((object)currentType != null);
            implementingType = null;
            return false;
        }
        [return: System.Runtime.CompilerServices.Nullable(2)]
        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));
        }
        [System.Runtime.CompilerServices.NullableContext(2)]
        public static void GetDictionaryKeyValueTypes([System.Runtime.CompilerServices.Nullable(1)] Type dictionaryType, out Type keyType, out Type valueType)
        {
            ValidationUtils.ArgumentNotNull(dictionaryType, "dictionaryType");
            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;
            case MemberTypes.Method:
                return ((MethodInfo)member).ReturnType;
            default:
                throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo, EventInfo or MethodInfo", "member");
            }
        }
        public static bool IsByRefLikeType(Type type)
        {
            if (!type.IsValueType())
                return false;
            Attribute[] attributes = GetAttributes(type, null, false);
            for (int i = 0; i < attributes.Length; i++) {
                if (string.Equals(attributes[i].GetType().FullName, "System.Runtime.CompilerServices.IsByRefLikeAttribute", StringComparison.Ordinal))
                    return true;
            }
            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, member.Name), "member");
            }
        }
        public static void SetMemberValue(MemberInfo member, object target, [System.Runtime.CompilerServices.Nullable(2)] 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 (object)propertyInfo.GetGetMethod(nonPublic) != 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.IsLiteral)
                    return false;
                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 (object)propertyInfo.GetSetMethod(nonPublic) != null;
            }
            default:
                return false;
            }
        }
        public static List<MemberInfo> GetFieldsAndProperties(Type type, BindingFlags bindingAttr)
        {
            List<MemberInfo> list = new List<MemberInfo>();
            ((IList<MemberInfo>)list).AddRange((IEnumerable)GetFields(type, bindingAttr));
            ((IList<MemberInfo>)list).AddRange((IEnumerable)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) {
                if (item.Count() == 1)
                    list2.Add(item.First());
                else {
                    List<MemberInfo> list3 = new List<MemberInfo>();
                    foreach (MemberInfo item2 in item) {
                        if (list3.Count == 0)
                            list3.Add(item2);
                        else if ((!IsOverridenGenericMember(item2, bindingAttr) || item2.Name == "Item") && !list3.Any((MemberInfo m) => (object)m.DeclaringType == item2.DeclaringType)) {
                            list3.Add(item2);
                        }
                    }
                    list2.AddRange(list3);
                }
            }
            return list2;
        }
        private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr)
        {
            if (memberInfo.MemberType() != MemberTypes.Property)
                return false;
            PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
            if (!propertyInfo.IsVirtual())
                return false;
            Type declaringType = propertyInfo.DeclaringType;
            if (!declaringType.IsGenericType())
                return false;
            Type genericTypeDefinition = declaringType.GetGenericTypeDefinition();
            if ((object)genericTypeDefinition == null)
                return false;
            MemberInfo[] member = genericTypeDefinition.GetMember(propertyInfo.Name, bindingAttr);
            if (member.Length == 0)
                return false;
            if (!GetMemberUnderlyingType(member[0]).IsGenericParameter)
                return false;
            return true;
        }
        [return: System.Runtime.CompilerServices.Nullable(2)]
        public static T GetAttribute<[System.Runtime.CompilerServices.Nullable(0)] T>(object attributeProvider) where T : Attribute
        {
            return GetAttribute<T>(attributeProvider, true);
        }
        [return: System.Runtime.CompilerServices.Nullable(2)]
        public static T GetAttribute<[System.Runtime.CompilerServices.Nullable(0)] T>(object attributeProvider, bool inherit) where T : Attribute
        {
            T[] attributes = GetAttributes<T>(attributeProvider, inherit);
            if (attributes == null)
                return null;
            return attributes.FirstOrDefault();
        }
        public static T[] GetAttributes<[System.Runtime.CompilerServices.Nullable(0)] T>(object attributeProvider, bool inherit) where T : Attribute
        {
            Attribute[] attributes = GetAttributes(attributeProvider, typeof(T), inherit);
            T[] array = attributes as T[];
            if (array != null)
                return array;
            return attributes.Cast<T>().ToArray();
        }
        public static Attribute[] GetAttributes(object attributeProvider, [System.Runtime.CompilerServices.Nullable(2)] Type attributeType, bool inherit)
        {
            ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider");
            Type type = attributeProvider as Type;
            if ((object)type != null) {
                Attribute[] array = (((object)attributeType != null) ? type.GetCustomAttributes(attributeType, inherit) : type.GetCustomAttributes(inherit)).Cast<Attribute>().ToArray();
                if (inherit && (object)type.BaseType != null)
                    array = array.Union(GetAttributes(type.BaseType, attributeType, inherit)).ToArray();
                return array;
            }
            Assembly assembly = attributeProvider as Assembly;
            if ((object)assembly != null) {
                if ((object)attributeType == null)
                    return Attribute.GetCustomAttributes(assembly);
                return Attribute.GetCustomAttributes(assembly, attributeType);
            }
            MemberInfo memberInfo = attributeProvider as MemberInfo;
            if ((object)memberInfo != null) {
                if ((object)attributeType == null)
                    return Attribute.GetCustomAttributes(memberInfo, inherit);
                return Attribute.GetCustomAttributes(memberInfo, attributeType, inherit);
            }
            Module module = attributeProvider as Module;
            if ((object)module != null) {
                if ((object)attributeType == null)
                    return Attribute.GetCustomAttributes(module, inherit);
                return Attribute.GetCustomAttributes(module, attributeType, inherit);
            }
            ParameterInfo parameterInfo = attributeProvider as ParameterInfo;
            if (parameterInfo != null) {
                if ((object)attributeType == null)
                    return Attribute.GetCustomAttributes(parameterInfo, inherit);
                return Attribute.GetCustomAttributes(parameterInfo, attributeType, inherit);
            }
            ICustomAttributeProvider customAttributeProvider = (ICustomAttributeProvider)attributeProvider;
            return (Attribute[])(((object)attributeType != null) ? customAttributeProvider.GetCustomAttributes(attributeType, inherit) : customAttributeProvider.GetCustomAttributes(inherit));
        }
        [return: System.Runtime.CompilerServices.Nullable(new byte[] {
            0,
            2,
            1
        })]
        public static StructMultiKey<string, string> SplitFullyQualifiedTypeName(string fullyQualifiedTypeName)
        {
            int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);
            string v;
            string v2;
            if (assemblyDelimiterIndex.HasValue) {
                v = fullyQualifiedTypeName.Trim(0, assemblyDelimiterIndex.GetValueOrDefault());
                v2 = fullyQualifiedTypeName.Trim(assemblyDelimiterIndex.GetValueOrDefault() + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.GetValueOrDefault() - 1);
            } else {
                v = fullyQualifiedTypeName;
                v2 = null;
            }
            return new StructMultiKey<string, string>(v2, v);
        }
        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)
        {
            if (memberInfo.MemberType() == 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 ((object)(targetType = targetType.BaseType()) != null) {
                    IEnumerable<FieldInfo> collection = from f in targetType.GetFields(bindingAttr2)
                    where f.IsPrivate
                    select f;
                    initialFields.AddRange((IEnumerable)collection);
                }
            }
        }
        public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
        {
            ValidationUtils.ArgumentNotNull(targetType, "targetType");
            List<PropertyInfo> list = new List<PropertyInfo>(targetType.GetProperties(bindingAttr));
            if (targetType.IsInterface()) {
                Type[] interfaces = targetType.GetInterfaces();
                foreach (Type type in interfaces) {
                    list.AddRange(type.GetProperties(bindingAttr));
                }
            }
            GetChildPrivateProperties(list, targetType, bindingAttr);
            for (int j = 0; j < list.Count; j++) {
                PropertyInfo propertyInfo = list[j];
                if ((object)propertyInfo.DeclaringType != targetType) {
                    PropertyInfo propertyInfo3 = list[j] = (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 ((object)(targetType = targetType.BaseType()) != null) {
                PropertyInfo[] properties = targetType.GetProperties(bindingAttr);
                foreach (PropertyInfo propertyInfo in properties) {
                    PropertyInfo subTypeProperty = propertyInfo;
                    if (!subTypeProperty.IsVirtual()) {
                        if (!IsPublic(subTypeProperty)) {
                            int num = initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name);
                            if (num == -1)
                                initialProperties.Add(subTypeProperty);
                            else if (!IsPublic(initialProperties[num])) {
                                initialProperties[num] = subTypeProperty;
                            }
                        } else if (initialProperties.IndexOf(delegate(PropertyInfo p) {
                            if (p.Name == subTypeProperty.Name)
                                return (object)p.DeclaringType == subTypeProperty.DeclaringType;
                            return false;
                        }) == -1) {
                            initialProperties.Add(subTypeProperty);
                        }
                    } else {
                        Type subTypePropertyDeclaringType = subTypeProperty.GetBaseDefinition()?.DeclaringType ?? subTypeProperty.DeclaringType;
                        if (initialProperties.IndexOf(delegate(PropertyInfo p) {
                            if (p.Name == subTypeProperty.Name && p.IsVirtual())
                                return (p.GetBaseDefinition()?.DeclaringType ?? p.DeclaringType).IsAssignableFrom(subTypePropertyDeclaringType);
                            return false;
                        }) == -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 && (object)info.DeclaringType != methodDeclaringType)
                    return (object)info.GetBaseDefinition().DeclaringType == methodDeclaringType;
                return false;
            });
        }
        [return: System.Runtime.CompilerServices.Nullable(2)]
        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 decimal.Zero;
                case PrimitiveTypeCode.DateTime:
                    return default(DateTime);
                case PrimitiveTypeCode.Guid:
                    return default(Guid);
                default:
                    if (IsNullable(type))
                        return null;
                    return Activator.CreateInstance(type);
                }
            }
            return null;
        }
    }
}