using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace CPF.Windows.Json.Deserialize { internal class ResolveFind { internal static ResolveDelegate Find() { Type t = typeof(T); return FindTypeIsDefaultImplemented(t) ?? FindTypeIsMeetDefaultCondition(t) ?? FindTypeIsDefaultImplementedBaseType(t) ?? FindTypeIsDefaultImplementedInterface(t) ?? DefaultResolve(t); } private static ResolveDelegate FindTypeIsDefaultImplemented(Type t) { if (DeserializeBootTable.Table.DefaultSameTypes.TryGetValue(t, out var member)) return GenerateLambdaCall(member); return null; } private static ResolveDelegate FindTypeIsMeetDefaultCondition(Type t) { return IsArray(t) ?? IsEnum(t) ?? IsDynamic(t); } private static ResolveDelegate FindTypeIsDefaultImplementedBaseType(Type t) { var baseTypes = t.GetTypeAndBaseTypes(); //Avoid if (DeserializeBootTable.Table.DefaultAvoidTypes.Intersect(baseTypes).Any()) return GenerateLambdaCall(SpecialConditionsResolve._ReadAvoidNull); //BaseType foreach (var item in DeserializeBootTable.Table.DefaultImplementedBaseType) { var implementedType = item.Key; foreach (var baseType in baseTypes) { if (baseType == implementedType) { return GenerateLambdaCall(item.Value.MethodInfo); } } } return null; } private static ResolveDelegate FindTypeIsDefaultImplementedInterface(Type t) { var intserfaces = t.GetInterfaces().ToList(); if (t.IsInterface) intserfaces.Add(t); foreach (var item in DeserializeBootTable.Table.DefaultImplementedInterfaces) { var implementedInterfaces = item.Key; foreach (var objInterface in intserfaces) { if (objInterface == implementedInterfaces) { return GenerateLambdaCall(item.Value.MethodInfo); } } } return null; } private static ResolveDelegate DefaultResolve(Type t) { Func> func = TypeIsDictionary(t) ?? TypeIsCollection(t) ?? TypeIsSpecial(t); if (func != null) return func(); return BuildFactory.Build(DeserializeBuildTypeEnum.KeyValueObject, t); } private static Func> TypeIsCollection(Type t) { return TypeIsCollectionInterface(t) ?? TypeIsCollectionType(t); } private static Func> TypeIsDictionary(Type t) { return TypeIsDictionaryInterface(t) ?? TypeIsDictionaryType(t); } private static Func> TypeIsSpecial(Type t) { if (t.IsGenericType) { var genericTypeDefinition = t.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(Nullable<>)) return () => GenerateLambdaCall(SpecialConditionsResolve._ReadNullable.MakeGenericMethod(t.GetGenericArguments()[0])); else if (genericTypeDefinition == typeof(Lazy<>)) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.Lazy, t); } else if (genericTypeDefinition == typeof(Lookup<,>)) { } else if (genericTypeDefinition == typeof(KeyValuePair<,>)) { var keyType = t.GetGenericArguments()[0]; var func = IsWrongKeyType(keyType); if (func != null) return () => func; return () => BuildFactory.Build(DeserializeBuildTypeEnum.KeyValuePair, t); } else if (genericTypeDefinition == typeof(ILookup<,>)) { } } return null; } private static Func> TypeIsCollectionInterface(Type t) { if (t == typeof(IEnumerable) || t == typeof(ICollection) || t == typeof(IList)) return () => BuildFactory.Build(DeserializeBuildTypeEnum.Collection, t, typeof(List), typeof(List), typeof(object)); if (t.IsGenericType) { var genericTypeDefinition = t.GetGenericTypeDefinition(); var arrayItemType = t.GetGenericArguments()[0]; if (genericTypeDefinition == typeof(IEnumerable<>) || genericTypeDefinition == typeof(IList<>) || genericTypeDefinition == typeof(ICollection<>)) return () => BuildFactory.Build(DeserializeBuildTypeEnum.Collection, t, typeof(List<>).MakeGenericType(arrayItemType), typeof(List<>).MakeGenericType(arrayItemType), arrayItemType); #if !Net4 if (genericTypeDefinition == typeof(IReadOnlyList<>) || genericTypeDefinition == typeof(IReadOnlyCollection<>)) { var ctor = typeof(ReadOnlyCollection<>).MakeGenericType(arrayItemType).GetCtorByParameterInterfaceType(typeof(IList<>).MakeGenericType(arrayItemType)); return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, typeof(ReadOnlyCollection<>).MakeGenericType(arrayItemType), ctor); } #endif if (genericTypeDefinition == typeof(ISet<>)) { var ctor = typeof(HashSet<>).MakeGenericType(arrayItemType).GetCtorByParameterInterfaceType(typeof(IEnumerable<>).MakeGenericType(arrayItemType)); return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, typeof(HashSet<>).MakeGenericType(arrayItemType), ctor); } } return null; } private static Func> TypeIsDictionaryInterface(Type t) { if (t == typeof(IDictionary)) return () => BuildFactory.Build(DeserializeBuildTypeEnum.Dictionary, t, typeof(Dictionary), typeof(Dictionary), typeof(string), typeof(object)); if (t.IsGenericType) { Type[] args = t.GetGenericArguments(); if (args.Length != 2) return null; var genericTypeDefinition = t.GetGenericTypeDefinition(); var keyType = args[0]; var valueType = args[1]; if (genericTypeDefinition == typeof(IDictionary<,>)) return () => BuildFactory.Build(DeserializeBuildTypeEnum.Dictionary, t, typeof(Dictionary<,>).MakeGenericType(keyType, valueType), t, keyType, valueType); #if !Net4 if (genericTypeDefinition == typeof(IReadOnlyDictionary<,>)) { var ctor = typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType).GetCtorByParameterInterfaceType(typeof(IDictionary<,>).MakeGenericType(keyType, valueType)); return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType), ctor); } #endif } return null; } private static Func> TypeIsCollectionType(Type t) { if (t.IsInterface) return null; var intserfaces = t.GetInterfaces(); bool hasIEnumerableGeneric = false; bool hasICollectionGeneric = false; bool hasICollection = false; bool hasIList = false; Type arrayItemType = null; Type iCollectionGenericType = null; Type iEnumerableGenericType = null; foreach (var item in intserfaces) { if (item.IsGenericType) { var genericTypeDefinition = item.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(IEnumerable<>)) { hasIEnumerableGeneric = true; arrayItemType = item.GetGenericArguments()[0]; iEnumerableGenericType = item; } else if (genericTypeDefinition == typeof(ICollection<>)) { hasICollectionGeneric = true; arrayItemType = item.GetGenericArguments()[0]; iCollectionGenericType = item; } } else if (item == typeof(ICollection)) hasICollection = true; else if (item == typeof(IList)) hasIList = true; } if (hasICollectionGeneric) { var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(iCollectionGenericType); if (ctor == null) { foreach (var item in t.GetConstructors()) { if (item.GetParameters().Length == 1) { var firstCtor = item.GetParameters()[0]; if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item); } } } } else if (ctor.GetParameters().Length == 0) //如果空的构造函数,则调用接口Add方法 { return () => BuildFactory.Build(DeserializeBuildTypeEnum.Collection, t, t, iCollectionGenericType, arrayItemType); } else //如果构造函数为iCollectionGenericType,则注入iCollectionGenericType return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, iCollectionGenericType, ctor); } if (hasIEnumerableGeneric && hasICollection) { var ctor = t.GetAppointTypeCtor(iEnumerableGenericType); if (ctor == null) { foreach (var item in t.GetConstructors()) { if (item.GetParameters().Length == 1) { var firstCtor = item.GetParameters()[0]; if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item); } } } } else return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, iEnumerableGenericType, ctor); } if (hasIList) { var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(typeof(IList)); if (ctor == null) { foreach (var item in t.GetConstructors()) { if (item.GetParameters().Length == 1) { var firstCtor = item.GetParameters()[0]; if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item); } } } } else if (ctor.GetParameters().Length == 0) //如果空的构造函数,则调用接口Add方法 { return () => BuildFactory.Build(DeserializeBuildTypeEnum.Collection, t, t, typeof(IList), typeof(object)); } else //如果构造函数为iCollectionGenericType,则注入iCollectionGenericType return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, typeof(IList), ctor); } if (hasICollection) { var ctor = t.GetAppointTypeCtor(typeof(ICollection)); if (ctor == null) { foreach (var item in t.GetConstructors()) { if (item.GetParameters().Length == 1) { var firstCtor = item.GetParameters()[0]; if (firstCtor.ParameterType.IsArray || TypeIsCollection(firstCtor.ParameterType) != null) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item); } } } } else return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, typeof(ICollection), ctor); } return null; } private static Func> TypeIsDictionaryType(Type t) { if (t.IsInterface) return null; var intserfaces = t.GetInterfaces(); bool hasIDictionaryGeneric = false; bool hasIDictionary = false; Type iDictionaryGenericType = null; Type keyType = null; Type valueType = null; foreach (var item in intserfaces) { if (item.IsGenericType) { var genericTypeDefinition = item.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(IDictionary<,>)) { iDictionaryGenericType = item; hasIDictionaryGeneric = true; keyType = item.GetGenericArguments()[0]; valueType = item.GetGenericArguments()[1]; } } if (item == typeof(IDictionary)) hasIDictionary = true; } if (hasIDictionaryGeneric) { var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(iDictionaryGenericType); if (ctor == null) { foreach (var item in t.GetConstructors()) { if (item.GetParameters().Length == 1) { var firstCtor = item.GetParameters()[0]; if (TypeIsDictionary(firstCtor.ParameterType) != null) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item); } } } } else if (ctor.GetParameters().Length == 0) { return () => IsWrongKeyType(keyType) ?? BuildFactory.Build(DeserializeBuildTypeEnum.Dictionary, t, t, iDictionaryGenericType, keyType, valueType); } else return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, iDictionaryGenericType, ctor); } if (hasIDictionary) { var ctor = t.GetDefaultNoArgCtorOrAppointTypeCtor(typeof(IDictionary)); if (ctor == null) { foreach (var item in t.GetConstructors()) { if (item.GetParameters().Length == 1) { var firstCtor = item.GetParameters()[0]; if (TypeIsDictionary(firstCtor.ParameterType) != null) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item); } } } } else if (ctor.GetParameters().Length == 0) { return () => BuildFactory.Build(DeserializeBuildTypeEnum.Dictionary, t, t, typeof(IDictionary), typeof(string), typeof(object)); } else return () => BuildFactory.Build(DeserializeBuildTypeEnum.CtorInject, t, typeof(IDictionary), ctor); } return null; } private static ResolveDelegate IsArray(Type t) { if (t.IsArray) { int rank = t.GetArrayRank(); if (rank == 1) return BuildFactory.Build(DeserializeBuildTypeEnum.Array, t); else { Type sawtoothType = t.GetElementType(); int i = rank; while (i-- > 0) { var obj = Array.CreateInstance(sawtoothType, 0); sawtoothType = obj.GetType(); } return BuildFactory.Build(DeserializeBuildTypeEnum.MultiArray, t, sawtoothType, rank); } } return null; } private static ResolveDelegate IsEnum(Type t) { if (t.IsEnum) return GenerateLambdaCallWithEnqueueType(SpecialConditionsResolve._ReadEnum, t); return null; } private static ResolveDelegate IsDynamic(Type t) { if (t.IsAnonymousType()) return BuildFactory.Build(DeserializeBuildTypeEnum.Dynamic, t); return null; } private static ResolveDelegate IsWrongKeyType(Type keyType) { if (keyType.IsWrongKey()) return BuildFactory.Build(DeserializeBuildTypeEnum.WrongGenericKey); return null; } private static ResolveDelegate GenerateLambdaCall(MethodInfo methodInfo) { ParameterExpression readerArg = Expression.Parameter(typeof(JsonReader), "reader"); ParameterExpression handlerArg = Expression.Parameter(typeof(JsonDeserializeHandler), "handler"); var body = Expression.Call(methodInfo, readerArg, handlerArg); return Expression.Lambda>(body, readerArg, handlerArg).Compile(); } private static ResolveDelegate GenerateLambdaCallWithEnqueueType(MethodInfo methodInfo, Type t) { ParameterExpression readerArg = Expression.Parameter(typeof(JsonReader), "reader"); ParameterExpression handlerArg = Expression.Parameter(typeof(JsonDeserializeHandler), "handler"); MemberExpression option = Expression.MakeMemberAccess(handlerArg, JsonDeserializeHandler._Types); LabelTarget label = Expression.Label(t); var body = Expression.Block(Expression.Call(option, typeof(Queue).GetMethod("Enqueue"), Expression.Constant(t, typeof(Type))) , Expression.Return(label, Expression.Convert(Expression.Call(methodInfo, readerArg, handlerArg), t)), Expression.Label(label, Expression.Convert(Expression.Call(methodInfo, readerArg, handlerArg), t)) ); return Expression.Lambda>(body, readerArg, handlerArg).Compile(); } } }