460 lines
20 KiB
C#
Raw Normal View History

2023-11-21 23:05:03 +08:00
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();
}
}
}