460 lines
20 KiB
C#
460 lines
20 KiB
C#
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<T>
|
||
{
|
||
internal static ResolveDelegate<T> Find()
|
||
{
|
||
Type t = typeof(T);
|
||
return FindTypeIsDefaultImplemented(t) ?? FindTypeIsMeetDefaultCondition(t) ?? FindTypeIsDefaultImplementedBaseType(t) ?? FindTypeIsDefaultImplementedInterface(t) ?? DefaultResolve(t);
|
||
}
|
||
|
||
private static ResolveDelegate<T> FindTypeIsDefaultImplemented(Type t)
|
||
{
|
||
if (DeserializeBootTable.Table.DefaultSameTypes.TryGetValue(t, out var member))
|
||
return GenerateLambdaCall(member);
|
||
return null;
|
||
}
|
||
|
||
private static ResolveDelegate<T> FindTypeIsMeetDefaultCondition(Type t)
|
||
{
|
||
return IsArray(t) ?? IsEnum(t) ?? IsDynamic(t);
|
||
}
|
||
|
||
private static ResolveDelegate<T> 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<T> 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<T> DefaultResolve(Type t)
|
||
{
|
||
Func<ResolveDelegate<T>> func = TypeIsDictionary(t) ?? TypeIsCollection(t) ?? TypeIsSpecial(t);
|
||
if (func != null)
|
||
return func();
|
||
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.KeyValueObject, t);
|
||
}
|
||
|
||
private static Func<ResolveDelegate<T>> TypeIsCollection(Type t)
|
||
{
|
||
return TypeIsCollectionInterface(t) ?? TypeIsCollectionType(t);
|
||
}
|
||
private static Func<ResolveDelegate<T>> TypeIsDictionary(Type t)
|
||
{
|
||
return TypeIsDictionaryInterface(t) ?? TypeIsDictionaryType(t);
|
||
}
|
||
private static Func<ResolveDelegate<T>> 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<T>(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<T>(DeserializeBuildTypeEnum.KeyValuePair, t);
|
||
}
|
||
else if (genericTypeDefinition == typeof(ILookup<,>))
|
||
{
|
||
|
||
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private static Func<ResolveDelegate<T>> TypeIsCollectionInterface(Type t)
|
||
{
|
||
if (t == typeof(IEnumerable) || t == typeof(ICollection) || t == typeof(IList))
|
||
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Collection, t, typeof(List<object>), typeof(List<object>), 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<T>(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<T>(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<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(HashSet<>).MakeGenericType(arrayItemType), ctor);
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
private static Func<ResolveDelegate<T>> TypeIsDictionaryInterface(Type t)
|
||
{
|
||
if (t == typeof(IDictionary))
|
||
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dictionary, t, typeof(Dictionary<string, object>), typeof(Dictionary<string, object>), 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<T>(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<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType), ctor);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
return null;
|
||
}
|
||
private static Func<ResolveDelegate<T>> 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<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (ctor.GetParameters().Length == 0) //如果空的构造函数,则调用接口Add方法
|
||
{
|
||
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Collection, t, t, iCollectionGenericType, arrayItemType);
|
||
}
|
||
else //如果构造函数为iCollectionGenericType,则注入iCollectionGenericType
|
||
return () => BuildFactory.Build<T>(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<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
return () => BuildFactory.Build<T>(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<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (ctor.GetParameters().Length == 0) //如果空的构造函数,则调用接口Add方法
|
||
{
|
||
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Collection, t, t, typeof(IList), typeof(object));
|
||
}
|
||
else //如果构造函数为iCollectionGenericType,则注入iCollectionGenericType
|
||
return () => BuildFactory.Build<T>(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<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(ICollection), ctor);
|
||
|
||
}
|
||
|
||
|
||
return null;
|
||
}
|
||
private static Func<ResolveDelegate<T>> 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<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (ctor.GetParameters().Length == 0)
|
||
{
|
||
return () => IsWrongKeyType(keyType) ?? BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dictionary, t, t, iDictionaryGenericType, keyType, valueType);
|
||
}
|
||
else
|
||
return () => BuildFactory.Build<T>(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<T>(DeserializeBuildTypeEnum.CtorInject, t, firstCtor.ParameterType, item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (ctor.GetParameters().Length == 0)
|
||
{
|
||
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dictionary, t, t, typeof(IDictionary), typeof(string), typeof(object));
|
||
}
|
||
else
|
||
return () => BuildFactory.Build<T>(DeserializeBuildTypeEnum.CtorInject, t, typeof(IDictionary), ctor);
|
||
}
|
||
|
||
|
||
return null;
|
||
}
|
||
|
||
private static ResolveDelegate<T> IsArray(Type t)
|
||
{
|
||
if (t.IsArray)
|
||
{
|
||
int rank = t.GetArrayRank();
|
||
if (rank == 1)
|
||
return BuildFactory.Build<T>(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<T>(DeserializeBuildTypeEnum.MultiArray, t, sawtoothType, rank);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
private static ResolveDelegate<T> IsEnum(Type t)
|
||
{
|
||
if (t.IsEnum)
|
||
return GenerateLambdaCallWithEnqueueType(SpecialConditionsResolve._ReadEnum, t);
|
||
return null;
|
||
}
|
||
private static ResolveDelegate<T> IsDynamic(Type t)
|
||
{
|
||
if (t.IsAnonymousType())
|
||
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.Dynamic, t);
|
||
return null;
|
||
}
|
||
|
||
|
||
private static ResolveDelegate<T> IsWrongKeyType(Type keyType)
|
||
{
|
||
if (keyType.IsWrongKey())
|
||
return BuildFactory.Build<T>(DeserializeBuildTypeEnum.WrongGenericKey);
|
||
return null;
|
||
}
|
||
private static ResolveDelegate<T> 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<ResolveDelegate<T>>(body, readerArg, handlerArg).Compile();
|
||
}
|
||
private static ResolveDelegate<T> 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<Type>).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<ResolveDelegate<T>>(body, readerArg, handlerArg).Compile();
|
||
}
|
||
}
|
||
}
|