Exemplo n.º 1
0
        static Type FindGenericType(Type type)
        {
            return(InterfaceTypes.GetOrAdd(type, key =>
            {
                Type[] genericTypes = type.GetInterfaces();

                if (genericTypes != null)
                {
                    for (int i = 0; i < genericTypes.Length; i++)
                    {
                        var genericType = genericTypes[i];
                        if (genericType.IsGenericType && GenericIListType.IsAssignableFrom(genericType.GetGenericTypeDefinition()))
                        {
                            return genericType.GetGenericArguments()[0];
                        }
                    }
                }
                return ObjectType;
            }));
        }
        static void WriteDeserializerList(TypeBuilder typeBuilder, ILGenerator il, Type type, int tag, MethodInfo setMethod,
                                          int?itemLocalIndex = null)
        {
            bool useGenericArguments;
            var  itemType = GetGenericListType(type, out useGenericArguments);//type.GetGenericArguments()[0];

            if (useGenericArguments && GenericIListType.IsAssignableFrom(type.GetGenericTypeDefinition()))
            {
                type = GenericListType.MakeGenericType(itemType);
            }


            var lengthLocal = il.DeclareLocal(typeof(int));
            var listLocal   = il.DeclareLocal(type);
            var itemLocal   = il.DeclareLocal(itemType);
            var indexLocal  = il.DeclareLocal(typeof(int));
            var startLabel  = il.DefineLabel();
            var endLabel    = il.DefineLabel();

            var hasLocalList = setMethod != null || itemLocalIndex != null;

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldarg_3);
            il.Emit(OpCodes.Ldc_I4, tag);
            il.Emit(OpCodes.Call, GetCollectionLengthMethod);
            il.Emit(OpCodes.Stloc, lengthLocal);


            if (hasLocalList)
            {
                var lengthCtor = type.GetConstructor(CtorCapacityTypes);

                if (lengthCtor != null)
                {
                    il.Emit(OpCodes.Ldloc, lengthLocal.LocalIndex);
                    il.Emit(OpCodes.Newobj, lengthCtor);
                    il.Emit(OpCodes.Stloc, listLocal.LocalIndex);
                }
                else
                {
                    il.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
                    il.Emit(OpCodes.Stloc, listLocal.LocalIndex);
                }
            }

            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc, indexLocal.LocalIndex);
            il.Emit(OpCodes.Br, startLabel);
            il.MarkLabel(endLabel);

            WriteDeserializerReadValue(typeBuilder, il, itemType, 1, itemLocal.LocalIndex);

            if (hasLocalList)
            {
                il.Emit(OpCodes.Ldloc, listLocal.LocalIndex);
            }
            else
            {
                il.Emit(OpCodes.Ldarg_1);
            }


            il.Emit(OpCodes.Ldloc, itemLocal.LocalIndex);
            il.Emit(OpCodes.Callvirt, type.GetMethod("Add", new[] { itemType }));


            il.Emit(OpCodes.Ldloc, indexLocal.LocalIndex);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc, indexLocal.LocalIndex);
            il.MarkLabel(startLabel);
            il.Emit(OpCodes.Ldloc, indexLocal.LocalIndex);
            il.Emit(OpCodes.Ldloc, lengthLocal.LocalIndex);
            il.Emit(OpCodes.Blt, endLabel);

            if (setMethod != null && itemLocalIndex == null)
            {
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldloc, listLocal.LocalIndex);
                il.Emit(OpCodes.Callvirt, setMethod);
            }
            else if (itemLocalIndex != null)
            {
                il.Emit(OpCodes.Ldloc, listLocal.LocalIndex);
                il.Emit(OpCodes.Stloc, itemLocalIndex.Value);
            }
        }