Ejemplo n.º 1
0
        static Type GenerateSerializer(Type objType)
        {
            Type returnType;

            if (CachedType.TryGetValue(objType, out returnType))
            {
                return(returnType);
            }
            var genericType = SerializerType.MakeGenericType(objType);
            var newTypeName = objType.Name + "Serializer";
            var assembly    = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName(newTypeName + "Class")
            {
                Version = new Version(1, 0, 0, 0)
            }, AssemblyBuilderAccess.RunAndSave);
            var module = assembly.DefineDynamicModule(newTypeName + ".dll");

            var type = module.DefineType(newTypeName,
                                         TypeAttributes.Public | TypeAttributes.Serializable | TypeAttributes.Sealed,
                                         typeof(Object), new[] { genericType });



            var methodSerialize = type.DefineMethod("ISerializer.Serialize", MethodAttribute,
                                                    ByteArrayType, new[] { objType });

            var methodDeserialize = type.DefineMethod("ISerializer.Deserialize", MethodAttribute,
                                                      objType, new[] { ByteArrayType });

            var methodDeserializeStream = type.DefineMethod("ISerializer.Deserialize", MethodAttribute,
                                                            objType, new[] { StreamType });

            var methodSerializeStream = type.DefineMethod("ISerializer.Serialize", MethodAttribute,
                                                          VoidType, new[] { objType, StreamType });

            var methodSerializeIL         = methodSerialize.GetILGenerator();
            var methodDeserializeIL       = methodDeserialize.GetILGenerator();
            var methodDeserializeStreamIL = methodDeserializeStream.GetILGenerator();
            var methodSerializeStreamIL   = methodSerializeStream.GetILGenerator();

            var bufferLocal       = methodSerializeIL.DeclareLocal(BufferStreamType);
            var bufferStreamLocal = methodSerializeStreamIL.DeclareLocal(BufferStreamType);

            var returnLocal     = methodDeserializeIL.DeclareLocal(objType);
            var startIndexLocal = methodDeserializeIL.DeclareLocal(typeof(int));

            methodDeserializeIL.Emit(OpCodes.Ldc_I4_0);
            methodDeserializeIL.Emit(OpCodes.Stloc, startIndexLocal.LocalIndex);


            var returnLocalStream     = methodDeserializeStreamIL.DeclareLocal(objType);
            var startIndexLocalStream = methodDeserializeStreamIL.DeclareLocal(typeof(int));

            methodDeserializeStreamIL.Emit(OpCodes.Ldc_I4_0);
            methodDeserializeStreamIL.Emit(OpCodes.Stloc, startIndexLocalStream.LocalIndex);

            //Serialize
            methodSerializeIL.Emit(OpCodes.Newobj, BufferStreamCtor);
            methodSerializeIL.Emit(OpCodes.Stloc, bufferLocal.LocalIndex);

            GenerateSerializerCallClassMethod(type, methodSerializeIL, objType, bufferLocal.LocalIndex);

            methodSerializeIL.Emit(OpCodes.Ldloc, bufferLocal.LocalIndex);
            methodSerializeIL.Emit(OpCodes.Callvirt, BufferStreamToArrayMethod);
            methodSerializeIL.Emit(OpCodes.Ret);


            //SerializeStream
            methodSerializeStreamIL.Emit(OpCodes.Ldarg_2);
            methodSerializeStreamIL.Emit(OpCodes.Newobj, BufferStreamStreamCtor);
            methodSerializeStreamIL.Emit(OpCodes.Stloc, bufferStreamLocal.LocalIndex);

            GenerateSerializerCallClassMethod(type, methodSerializeStreamIL, objType, bufferStreamLocal.LocalIndex);


            methodSerializeStreamIL.Emit(OpCodes.Ret);

            //Deserialize
            GenerateDeserializerCallClassMethod(type, methodDeserializeIL, objType, returnLocal.LocalIndex,
                                                startIndexLocal.LocalIndex);

            methodDeserializeIL.Emit(OpCodes.Ldloc_S, returnLocal.LocalIndex);
            methodDeserializeIL.Emit(OpCodes.Ret);


            //DeserializeStream
            GenerateDeserializerCallClassMethod(type, methodDeserializeStreamIL, objType, returnLocalStream.LocalIndex,
                                                startIndexLocalStream.LocalIndex, useStream: true);

            methodDeserializeStreamIL.Emit(OpCodes.Ldloc, returnLocalStream.LocalIndex);
            methodDeserializeStreamIL.Emit(OpCodes.Ret);

            //Override interface implementation
            type.DefineMethodOverride(methodSerialize,
                                      genericType.GetMethod("Serialize", new[] { objType }));
            type.DefineMethodOverride(methodDeserialize,
                                      genericType.GetMethod("Deserialize", new[] { ByteArrayType }));
            type.DefineMethodOverride(methodDeserializeStream,
                                      genericType.GetMethod("Deserialize", new[] { StreamType }));
            type.DefineMethodOverride(methodSerializeStream,
                                      genericType.GetMethod("Serialize", new[] { objType, StreamType }));

            returnType          = type.CreateType();
            CachedType[objType] = returnType;

            if (BinarySerializer.GenerateAssembly)
            {
                assembly.Save(newTypeName + ".dll");
            }
            return(returnType);
        }