csharp/1996v/Bssom.Net/Bssom.Serializer/Resolvers/ICollectionResolver.cs

ICollectionResolver.cs
//using System.Runtime.CompilerServices;

using Bssom.Serializer.Formatters;
using Bssom.Serializer.Internal;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;

namespace Bssom.Serializer.Resolvers
{
    /// 
    /// 获取和生成具有IColloction行为的类型的
    /// Get and generate the type with IColloction behavior 
    /// 
    public sealed clast ICollectionResolver : IFormatterResolver
    {
        internal const string ModuleName = "Bssom.Serializer.Resolvers.IColloctionResolver";
        internal static readonly DynamicFormatterastembly Dynamicastembly;

        /// 
        /// The singleton instance that can be used.
        /// 
        public static readonly ICollectionResolver Instance;

        static ICollectionResolver()
        {
            Instance = new ICollectionResolver();
            Dynamicastembly = new DynamicFormatterastembly(ModuleName);
        }

        public IBssomFormatter GetFormatter()
        {
            return FormatterCache.Formatter;
        }

        private static clast FormatterCache
        {
            public static readonly IBssomFormatter Formatter;

            static FormatterCache()
            {
                Type t = typeof(T);

                if (Array1ResolverGetFormatterHelper.TryGetFormatter(t, out IBssomFormatter formatter))
                {
                    Formatter = (IBssomFormatter)formatter;
                    return;
                }

                if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ArraySegment))
                {
                    Formatter = (IBssomFormatter)Activator.CreateInstance(typeof(ArraySegmentFormatter).MakeGenericType(t.GetGenericArguments()));
                    return;
                }

                if (TypeIsArray(t, out int rank, out Type elementType))
                {
                    if (rank == 1)
                    {
                        Formatter = (IBssomFormatter)Activator.CreateInstance(typeof(OneDimensionalArrayFormatter).MakeGenericType(elementType));
                    }
                    else if (rank == 2)
                    {
                        Formatter = (IBssomFormatter)Activator.CreateInstance(typeof(TwoDimensionalArrayFormatter).MakeGenericType(elementType));
                    }
                    else if (rank == 3)
                    {
                        Formatter = (IBssomFormatter)Activator.CreateInstance(typeof(ThreeDimensionalArrayFormatter).MakeGenericType(elementType));
                    }
                    else if (rank == 4)
                    {
                        Formatter = (IBssomFormatter)Activator.CreateInstance(typeof(FourDimensionalArrayFormatter).MakeGenericType(elementType));
                    }
                    else
                    {
                        throw BssomSerializationTypeFormatterException.UnsupportedType(t);
                    }
                    return;
                }

                if (TypeIsCollection(t,
                    out ConstructorInfo constructor,
                    out Type itemType,
                    out bool isImplGenerIList, out bool IsImplIList, out bool isImplGenerICollec, out bool isImplIReadOnlyList))
                {
                    TypeInfo buildType;
                    if (t.IsInterface)
                    {
                        buildType = ICollectionFormatterTypeBuilder.BuildICollectionInterfaceType(Dynamicastembly, t, itemType);
                    }
                    else
                    {
                        buildType = ICollectionFormatterTypeBuilder.BuildICollectionImplementationType(Dynamicastembly, t, constructor, itemType, isImplGenerIList, IsImplIList, isImplGenerICollec, isImplIReadOnlyList);
                    }

                    Formatter = (IBssomFormatter)Activator.CreateInstance(buildType);
                }
            }
        }


        internal static bool TypeIsCollection(Type t, out ConstructorInfo constructor, out Type itemType, out bool isImplGenerIList, out bool IsImplIList, out bool isImplGenerICollec, out bool isImplIReadOnlyList)
        {
            constructor = null;
            itemType = null;
            IsImplIList = false;
            isImplGenerIList = false;
            isImplGenerICollec = false;
            isImplIReadOnlyList = false;

            if (t.IsInterface)
            {
                if (t == typeof(IEnumerable) || t == typeof(ICollection) || t == typeof(IList))
                {
                    itemType = typeof(object);
                    if (t == typeof(IList))
                    {
                        IsImplIList = true;
                    }

                    return true;
                }

                if (t.IsGenericType)
                {
                    Type genericType = t.GetGenericTypeDefinition();
                    if (genericType == typeof(IEnumerable) || genericType == typeof(IList) || genericType == typeof(ICollection) || genericType == typeof(ISet) || genericType == typeof(IReadOnlyList) || genericType == typeof(IReadOnlyCollection))
                    {
                        if (genericType == typeof(IList))
                        {
                            isImplGenerIList = true;
                            isImplGenerICollec = true;
                        }
                        else if (genericType == typeof(ICollection) || genericType == typeof(ISet))
                        {
                            isImplGenerICollec = true;
                        }
                        else if (genericType == typeof(IReadOnlyList))
                        {
                            isImplIReadOnlyList = true;
                        }

                        itemType = t.GetGenericArguments()[0];
                        return true;
                    }
                }

                return false;
            }

            if (t.IsGenericType)
            {
                Type genericType = t.GetGenericTypeDefinition();
                if (genericType == typeof(List))
                {
                    itemType = t.GetGenericArguments()[0];
                    isImplGenerIList = true;
                    IsImplIList = true;
                    isImplGenerICollec = true;
                    isImplIReadOnlyList = true;
                    constructor = t.GetConstructor(new Type[] { typeof(int) });
                    return true;
                }
            }

            bool isImplGenerIEnumerable = false;
            bool isImplICollection = false;
            Type generIEnumerableItemType = null;
            Type generILissatemType = null;
            Type generICollectionItemType = null;

            Type[] intserfaces = t.GetInterfaces();
            foreach (Type item in intserfaces)
            {
                if (item.IsGenericType)
                {
                    Type genericTypeDefinition = item.GetGenericTypeDefinition();

                    if (genericTypeDefinition == typeof(IEnumerable))
                    {
                        isImplGenerIEnumerable = true;
                        generIEnumerableItemType = item.GetGenericArguments()[0];
                    }
                    else if (genericTypeDefinition == typeof(ICollection))
                    {
                        isImplGenerICollec = true;
                        generICollectionItemType = item.GetGenericArguments()[0];
                    }
                    else if (genericTypeDefinition == typeof(IList))
                    {
                        isImplGenerIList = true;
                        generILissatemType = item.GetGenericArguments()[0];
                    }
                }
                else if (item == typeof(ICollection))
                {
                    isImplICollection = true;
                }
                else if (item == typeof(IList))
                {
                    IsImplIList = true;
                }
            }

            if (isImplGenerIList)
            {
                if (TryGetConstructorInfo(t, generILissatemType, true, out constructor))
                {
                    itemType = generILissatemType;
                    return true;
                }
            }

            if (isImplGenerICollec)
            {
                if (TryGetConstructorInfo(t, generICollectionItemType, true, out constructor))
                {
                    itemType = generICollectionItemType;
                    return true;
                }
            }

            if (isImplGenerIEnumerable && isImplICollection)
            {
                if (TryGetConstructorInfo(t, generIEnumerableItemType, false, out constructor))
                {
                    itemType = generIEnumerableItemType;
                    return true;
                }
            }

            if (IsImplIList)
            {
                if (TryGetConstructorInfo(t, typeof(object), true, out constructor))
                {
                    itemType = typeof(object);
                    return true;
                }
            }

            if (isImplICollection)
            {
                if (TryGetConstructorInfo(t, typeof(object), false, out constructor))
                {
                    itemType = typeof(object);
                    return true;
                }
            }

            return false;
        }

        private static bool TypeIsArray(Type t, out int rank, out Type elementType)
        {
            if (t.IsArray)
            {
                rank = t.GetArrayRank();
                elementType = t.GetElementType();
                return true;
            }
            rank = 0;
            elementType = null;
            return false;
        }

        private static bool TryGetConstructorInfo(Type targetType, Type itemType, bool isFindEmptyCtor, out ConstructorInfo constructor)
        {
            constructor = null;
            foreach (ConstructorInfo item in targetType.GetConstructors())
            {
                ParameterInfo[] paras = item.GetParameters();

                if (isFindEmptyCtor)
                {
                    if (paras.Length == 0)
                    {
                        constructor = item;
                        return true;
                    }
                }

                if (constructor != null)
                {
                    continue;
                }

                if (paras.Length == 1)
                {
                    Type ctorArgType = paras[0].ParameterType;
                    if (targetType == ctorArgType)
                    {
                        continue;
                    }

                    if (
                        (TypeIsArray(ctorArgType, out int rank, out Type eleType) &&
                        rank == 1 && eleType == itemType
                        ) ||
                       (TypeIsCollection(ctorArgType, out ConstructorInfo a, out eleType, out bool c, out bool d, out bool e, out bool f) &&
                       eleType == itemType)
                        )
                    {
                        constructor = item;
                        if (!isFindEmptyCtor)
                        {
                            return true;
                        }
                    }
                }
            }
            return constructor != null;
        }
    }
}

namespace Bssom.Serializer.Internal
{
    internal static clast Array1ResolverGetFormatterHelper
    {
        private static readonly Dictionary FormatterMap = new Dictionary()
        {
            { typeof(Int16[]), Int16ArrayFormatter.Instance },
            { typeof(Int32[]), Int32ArrayFormatter.Instance },
            { typeof(Int64[]), Int64ArrayFormatter.Instance },
            { typeof(UInt16[]), UInt16ArrayFormatter.Instance },
            { typeof(UInt32[]), UInt32ArrayFormatter.Instance },
            { typeof(UInt64[]), UInt64ArrayFormatter.Instance },
            { typeof(Single[]), Float32ArrayFormatter.Instance },
            { typeof(Double[]), Float64ArrayFormatter.Instance },
            { typeof(bool[]), BooleanArrayFormatter.Instance },
            { typeof(byte[]), UInt8ArrayFormatter.Instance },//special
            { typeof(sbyte[]), Int8ArrayFormatter.Instance },
            { typeof(char[]), CharArrayFormatter.Instance },
            { typeof(DateTime[]), DateTimeArrayFormatter.Instance },
            { typeof(Decimal[]), DecimalArrayFormatter.Instance },
            { typeof(Guid[]),GuidArrayFormatter.Instance },

            { typeof(List), Int16ListFormatter.Instance },
            { typeof(List), Int32ListFormatter.Instance },
            { typeof(List), Int64ListFormatter.Instance },
            { typeof(List), UInt16ListFormatter.Instance },
            { typeof(List), UInt32ListFormatter.Instance },
            { typeof(List), UInt64ListFormatter.Instance },
            { typeof(List), Float32ListFormatter.Instance },
            { typeof(List), Float64ListFormatter.Instance },
            { typeof(List), BooleanListFormatter.Instance },
            { typeof(List), UInt8ListFormatter.Instance },//special
            { typeof(List), Int8ListFormatter.Instance },
            { typeof(List), CharListFormatter.Instance },
            { typeof(List), DateTimeListFormatter.Instance },
            { typeof(List), DecimalListFormatter.Instance },
            { typeof(List),GuidListFormatter.Instance },

            { typeof(ArraySegment), BooleanArraySegmentFormatter.Instance },
            { typeof(ArraySegment), UInt8ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), Int8ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), Int16ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), UInt16ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), CharArraySegmentFormatter.Instance },
            { typeof(ArraySegment), Int32ArraySegmentFormatter.Instance },
            { typeof(ArraySegment),UInt32ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), Int64ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), UInt64ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), Float32ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), Float64ArraySegmentFormatter.Instance },
            { typeof(ArraySegment), DateTimeArraySegmentFormatter.Instance },
            { typeof(ArraySegment), DecimalArraySegmentFormatter.Instance },
            { typeof(ArraySegment),GuidArraySegmentFormatter.Instance },
        };

        internal static bool TryGetFormatter(Type t, out IBssomFormatter formatter)
        {
            if (FormatterMap.TryGetValue(t, out formatter))
            {
                return true;
            }

            return false;
        }

        internal static Type GetListFormatterType(Type itemType)
        {
            Type listT = typeof(List).MakeGenericType(itemType);
            return FormatterMap[listT].GetType();
        }
    }

    internal static clast ICollectionFormatterTypeBuilder
    {
        public static TypeInfo BuildICollectionInterfaceType(DynamicFormatterastembly astembly, Type type, Type elementType)
        {
            TypeBuilder typeBuilder = astembly.DefineCollectionFormatterType(type, elementType);

            MethodBuilder serializeMethod = TypeBuildHelper.DefineSerializeMethod(typeBuilder, type);
            MethodBuilder deserializeMethod = TypeBuildHelper.DefineDeserializeMethod(typeBuilder, type);
            MethodBuilder sizeMethod = TypeBuildHelper.DefineSizeMethod(typeBuilder, type);

            if (type.IsGenericType == false)
            {
                DEBUG.astert(type == typeof(IEnumerable) || type == typeof(IList) || type == typeof(ICollection));
                //itemType is Object, Array2
                if (type == typeof(IList))
                {
                    TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeIList), BindingFlags.Public | BindingFlags.Static));
                }
                else
                {
                    TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeIEnumerable), BindingFlags.Public | BindingFlags.Static));
                }

                TypeBuildHelper.CallOneMethodInDeserialize(deserializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.DeserializeList), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(typeof(object)));

                TypeBuildHelper.CallOneMethodInSize(sizeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SizeIEnumerable), BindingFlags.Public | BindingFlags.Static));
            }
            else
            {
                Type genericTypeDefine = type.GetGenericTypeDefinition();
                DEBUG.astert(genericTypeDefine == typeof(IEnumerable) || genericTypeDefine == typeof(IList) || genericTypeDefine == typeof(ICollection) || genericTypeDefine == typeof(ISet) || genericTypeDefine == typeof(IReadOnlyList) || genericTypeDefine == typeof(IReadOnlyCollection));

                if (Array1FormatterHelper.IsArray1Type(elementType))
                {
                    //Array1
                    TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array1FormatterHelper).GetMethod(nameof(Array1FormatterHelper.SerializeIEnumerable), new Type[] { typeof(BssomWriter).MakeByRefType(), typeof(BssomSerializeContext).MakeByRefType(), typeof(IEnumerable).MakeGenericType(elementType) }));

                    if (genericTypeDefine == typeof(ISet))
                    {
                        TypeBuildHelper.CallOneMethodInDeserialize(deserializeMethod, typeof(Array1FormatterHelper).GetMethod(Array1FormatterHelper.DeserializeSetPrefix + elementType.Name, BindingFlags.Public | BindingFlags.Static));
                    }
                    else
                    {
                        Type listFormatterType = Array1ResolverGetFormatterHelper.GetListFormatterType(elementType);
                        FieldInfo field = listFormatterType.GetField(nameof(DateTimeListFormatter.Instance), BindingFlags.Static | BindingFlags.Public);
                        MethodInfo method = listFormatterType.GetMethod(nameof(DateTimeListFormatter.Deserialize));
                        TypeBuildHelper.CallOneStaticFieldMethodInDeserialize(deserializeMethod, field, method);
                    }

                    TypeBuildHelper.CallOneMethodInSize(sizeMethod, typeof(Array1FormatterHelper).GetMethod(nameof(Array1FormatterHelper.SizeIEnumerable), new Type[] { typeof(BssomSizeContext).MakeByRefType(), typeof(IEnumerable).MakeGenericType(elementType) }));
                }
                else
                {
                    if (genericTypeDefine == typeof(IList) || genericTypeDefine == typeof(IReadOnlyList))
                    {
                        TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeGenerIList), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType));
                    }
                    else
                    {
                        TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeGenericIEnumerable), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType));
                    }

                    if (genericTypeDefine == typeof(ISet))
                    {
                        TypeBuildHelper.CallOneMethodInDeserialize(deserializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.DeserializeSet), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType));
                    }
                    else
                    {
                        TypeBuildHelper.CallOneMethodInDeserialize(deserializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.DeserializeList), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType));
                    }

                    TypeBuildHelper.CallOneMethodInSize(sizeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SizeGenericIEnumerable), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType));
                }
            }

            return typeBuilder.CreateTypeInfo();
        }

        public static TypeInfo BuildICollectionImplementationType(DynamicFormatterastembly astembly, Type type, ConstructorInfo constructor,
                     Type itemType,
                     bool isImplGenerIList, bool IsImplIList, bool isImplGenerICollec, bool isImplIReadOnlyList)
        {
            TypeBuilder typeBuilder = astembly.DefineFormatterType(type);

            MethodBuilder sizeMethod = TypeBuildHelper.DefineSizeMethod(typeBuilder, type);
            MethodBuilder serializeMethod = TypeBuildHelper.DefineSerializeMethod(typeBuilder, type);
            if (itemType == typeof(object))
            {
                //itemType is Object, Array2
                if (IsImplIList)
                {
                    TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeIList), BindingFlags.Public | BindingFlags.Static));
                }
                else
                {
                    TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeIEnumerable), BindingFlags.Public | BindingFlags.Static));
                }

                TypeBuildHelper.CallOneMethodInSize(sizeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SizeIEnumerable), BindingFlags.Public | BindingFlags.Static));
            }
            else
            {
                if (Array1FormatterHelper.IsArray1Type(itemType))
                {
                    //Array1
                    TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array1FormatterHelper).GetMethod(nameof(Array1FormatterHelper.SerializeIEnumerable), new Type[] { typeof(BssomWriter).MakeByRefType(), typeof(BssomSerializeContext).MakeByRefType(), typeof(IEnumerable).MakeGenericType(itemType) }));

                    TypeBuildHelper.CallOneMethodInSize(sizeMethod, typeof(Array1FormatterHelper).GetMethod(nameof(Array1FormatterHelper.SizeIEnumerable), new Type[] { typeof(BssomSizeContext).MakeByRefType(), typeof(IEnumerable).MakeGenericType(itemType) }));
                }
                else
                {
                    if (isImplGenerIList || isImplIReadOnlyList)
                    {
                        TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeGenerIList), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(itemType));
                    }
                    else
                    {
                        TypeBuildHelper.CallOneMethodInSerialize(serializeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SerializeGenericIEnumerable), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(itemType));
                    }

                    TypeBuildHelper.CallOneMethodInSize(sizeMethod, typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.SizeGenericIEnumerable), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(itemType));
                }
            }

            MethodBuilder deserializeMethod = TypeBuildHelper.DefineDeserializeMethod(typeBuilder, type);
            ParameterInfo[] args = constructor.GetParameters();
            if (args.Length == 1 && args[0].ParameterType != typeof(int))
            {
                //new T(IEnumerable t)
                Type dynamicCacheType = typeof(CollectionDynamicDelegateCache).MakeGenericType(type);
                MethodInfo methodinfo = dynamicCacheType.GetMethod(nameof(CollectionDynamicDelegateCache.GenerateInjectCtor));
                methodinfo.Invoke(null, new object[] { constructor, args[0].ParameterType });
                TypeBuildHelper.CallDeserializeDelegate(deserializeMethod, type, dynamicCacheType.GetField(nameof(CollectionDynamicDelegateCache.Deserialize), BindingFlags.Public | BindingFlags.Static));
            }
            else
            {
                if (itemType == typeof(DateTime))//DateTime需要特殊处理,因为要处理Standrand和Native
                {
                    Type dtCollBuilder = typeof(DateTimeCollectionDeserializeBuilder).MakeGenericType(type);
                    MethodInfo methodinfo = dtCollBuilder.GetMethod(nameof(DateTimeCollectionDeserializeBuilder.ConstructorInit));
                    methodinfo.Invoke(null, new object[] { constructor });

                    TypeBuildHelper.CallOneMethodInDeserialize(deserializeMethod, dtCollBuilder.GetMethod(nameof(DateTimeCollectionDeserializeBuilder.Deserialize)));
                }
                else
                {
                    Type dynamicCacheType = typeof(CollectionDynamicDelegateCache).MakeGenericType(type);
                    if (args.Length == 0)
                    {
                        MethodInfo methodinfo = dynamicCacheType.GetMethod(nameof(CollectionDynamicDelegateCache.GenerateDeserializeWithEmptyCtor));
                        methodinfo.Invoke(null, new object[] { constructor, isImplGenerICollec, itemType });
                    }
                    else
                    {
                        DEBUG.astert(args.Length == 1 && args[0].ParameterType == typeof(int));

                        MethodInfo methodinfo = dynamicCacheType.GetMethod(nameof(CollectionDynamicDelegateCache.GenerateDeserializeWithCapacityCtor));
                        methodinfo.Invoke(null, new object[] { constructor, isImplGenerICollec, itemType });
                    }
                    TypeBuildHelper.CallDeserializeDelegate(deserializeMethod, type, dynamicCacheType.GetField(nameof(CollectionDynamicDelegateCache.Deserialize), BindingFlags.Public | BindingFlags.Static));
                }
            }
            return typeBuilder.CreateTypeInfo();
        }
    }

    internal static clast DateTimeCollectionDeserializeBuilder where T : ICollection
    {
        private delegate T Ctor(ref BssomReader reader, int count);
        private static Ctor constructor;

        public static T Deserialize(ref BssomReader reader, ref BssomDeserializeContext context)
        {
            if (reader.TryReadNullWithEnsureBuildInType(BssomType.Array1))
            {
                return default;
            }

            byte type = reader.ReadBssomType();
            switch (type)
            {
                case BssomType.TimestampCode:
                    {
                        reader.SkipVariableNumber();
                        int len = reader.ReadVariableNumber();
                        T t = constructor(ref reader, len);
                        for (int i = 0; i < len; i++)
                        {
                            context.CancellationToken.ThrowIfCancellationRequested();
                            t.Add(reader.ReadStandDateTimeWithOutTypeHead());
                        }
                        return t;
                    }
                case BssomType.NativeCode:
                    {
                        reader.EnsureType(NativeBssomType.DateTimeCode);
                        reader.SkipVariableNumber();
                        int len = reader.ReadVariableNumber();
                        T t = constructor(ref reader, len);
                        for (int i = 0; i < len; i++)
                        {
                            context.CancellationToken.ThrowIfCancellationRequested();
                            t.Add(reader.ReadNativeDateTimeWithOutTypeHead());
                        }
                        return t;
                    }
                default:
                    throw BssomSerializationOperationException.UnexpectedCodeRead(type, reader.Position);
            }
        }

        public static void ConstructorInit(ConstructorInfo ctor)
        {
            ParameterInfo[] paras = ctor.GetParameters();
            ParameterExpression count = Expression.Parameter(typeof(int));
            Expression body;
            if (paras.Length == 0)
            {
                body = Expression.New(ctor);
            }
            else
            {
                body = Expression.New(ctor, count);
            }

            constructor = Expression.Lambda(body, CommonExpressionMeta.Par_Reader, count).Compile();
        }
    }

    internal static clast CollectionDynamicDelegateCache
    {
        public static Deserialize Deserialize;

        public static void GenerateDeserializeWithEmptyCtor(ConstructorInfo constructor, bool isImplGenerICollec, Type itemType)
        {
            GenerateDeserializeWithCore(isImplGenerICollec, itemType, (len) => Expression.New(constructor));
        }

        public static void GenerateDeserializeWithCapacityCtor(ConstructorInfo constructor, bool isImplGenerICollec, Type itemType)
        {
            GenerateDeserializeWithCore(isImplGenerICollec, itemType, (len) => Expression.New(constructor, len));
        }

        private static void GenerateDeserializeWithCore(bool isImplGenerICollec, Type itemType, Func ctor)
        {
            /*
               if (reader.TryReadNullWithEnsureArray1BuildInType(BssomType.Int8Code))/TryReadNullWithEnsureArray1NativeType(NativeBssomType.CharCode)/TryReadNullWithEnsureBuildInType(BssomType.Array2)
                    return default;
               context.option.Security.DepthStep(ref reader);
               reader.SkipVariableNumber();
               int len = reader.ReadVariableNumber();
               T t = new T(len);
               Fill(ref t,ref reader,ref context,len);
               context.Depth--;
               return t;  
            */

            bool isArray1Type = Array1FormatterHelper.IsArray1Type(itemType, out bool isNativeType, out byte typeCode, out string typeCodeName);
            Type t = typeof(T);
            List ary = new List(7);
            LabelTarget returnTarget = Expression.Label(t, "returnLable");

            if (isArray1Type)
            {
                if (isNativeType)
                {
                    //if (reader.ryReadNullWithEnsureArray1NativeType(NativeType))
                    //      goto label;
                    ary.Add(Expression.IfThen(CommonExpressionMeta.Call_Reader_TryReadNullWithEnsureArray1NativeType(typeCode), Expression.Return(returnTarget, Expression.Default(t))));
                }
                else
                {
                    //if (reader.Call_Reader_TryReadNullWithEnsureArray1BuildInType(BuildInType))
                    //      goto label;
                    ary.Add(Expression.IfThen(CommonExpressionMeta.Call_Reader_TryReadNullWithEnsureArray1BuildInType(typeCode), Expression.Return(returnTarget, Expression.Default(t))));
                }
            }
            else
            {
                //if (reader.TryReadNullWithEnsureBuildInType(BssomType.Array2))
                //      goto label;
                ary.Add(Expression.IfThen(CommonExpressionMeta.Call_Reader_TryReadNullWithEnsureBuildInType(BssomType.Array2), Expression.Return(returnTarget, Expression.Default(t))));
            }

            //context.option.Security.DepthStep(ref reader);
            ary.Add(CommonExpressionMeta.Call_DeserializeContext_Option_Security_DepthStep);

            //reader.SkipVariableNumber();
            ary.Add(CommonExpressionMeta.Call_Reader_SkipVariableNumber);

            //int len = reader.ReadVariableNumber();
            ParameterExpression len = Expression.Variable(typeof(int));
            ary.Add(Expression.astign(len, CommonExpressionMeta.Call_Reader_ReadVariableNumber));

            //T t = ctor(len);
            ParameterExpression instance = Expression.Variable(t);
            ary.Add(Expression.astign(instance, ctor(len)));
            MethodInfo method = null;
            if (isImplGenerICollec == false)
            {
                //IColloctionFormatterHelper.Fill_ImplIList(ref t,ref reader,ref context,len)
                method = typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.Fill_ImplIList), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(t);
            }
            else
            {
                if (isArray1Type)
                {
                    //IColloctionFormatterHelper.Fill{TypeCodeName}(ref t,ref reader,ref context,len)
                    method = typeof(Array1FormatterHelper).GetMethod(Array1FormatterHelper.FillPrefix + typeCodeName.ToString().Replace("Code", ""), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(t);
                }
                else
                {
                    //IColloctionFormatterHelper.Fill_ImplICollection(ref t,ref reader,ref context,len)
                    method = typeof(Array2FormatterHelper).GetMethod(nameof(Array2FormatterHelper.Fill_ImplICollection), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(new Type[] { t, itemType });
                }
            }

            ary.Add(Expression.Call(null, method, instance, CommonExpressionMeta.Par_Reader, CommonExpressionMeta.Par_DeserializeContext, len));
            //context.Depth--;
            ary.Add(CommonExpressionMeta.Call_DeserializeContext_Depth_Decrementastign);
            //return t;
            ary.Add(Expression.Return(returnTarget, instance));
            //label default(T)
            ary.Add(Expression.Label(returnTarget, instance));

            BlockExpression block = Expression.Block(new ParameterExpression[] { instance, len }, ary);
            Deserialize = Expression.Lambda(block, CommonExpressionMeta.Par_Reader, CommonExpressionMeta.Par_DeserializeContext).Compile();


        }

        public static void GenerateInjectCtor(ConstructorInfo constructor, Type injectType)
        {
            Deserialize = Expression.Lambda(CommonExpressionMeta.GenerateInjectCtor(typeof(T), constructor, injectType), CommonExpressionMeta.Par_Reader, CommonExpressionMeta.Par_DeserializeContext).Compile();
        }
    }
}