⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codegenerator.cs

📁 Perst开源实时数据库
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.Globalization;

namespace Perst.Impl
{
    /// <summary>
    /// Generate code for condition
    /// </summary>
    internal class CodeGenerator
    {
        public GeneratedSerializer Generate(ClassDescriptor desc)            
        {
            ModuleBuilder module = EmitAssemblyModule();
            Type newCls = EmitClass(module, desc);
            return (GeneratedSerializer)module.Assembly.CreateInstance(newCls.Name);
        }

        public Type CreateWrapper(Type type)            
        {
            return EmitClassWrapper(EmitAssemblyModule(), type);
        }

        private ModuleBuilder EmitAssemblyModule()
        {
            if (dynamicModule == null)
            {
                //
                //Create an assembly name
                //
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name = "GeneratedSerializerAssembly";
                //
                //Create a new assembly with one module
                //
                AssemblyBuilder assembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
                dynamicModule = assembly.DefineDynamicModule("GeneratedSerializerModule");
            }
            return dynamicModule;
        }
        
        private MethodBuilder GetBuilder(TypeBuilder serializerType, MethodInfo methodInterface)
        {
            Type returnType = methodInterface.ReturnType;
            ParameterInfo[] methodParams = methodInterface.GetParameters();
            Type[] paramTypes = new Type[methodParams.Length];
            for (int i = 0; i < methodParams.Length; i++) 
            {
                paramTypes[i] = methodParams[i].ParameterType;
            }
            return serializerType.DefineMethod(methodInterface.Name,
                MethodAttributes.Public | MethodAttributes.Virtual,
                returnType,
                paramTypes);            
        }


        private void generatePackField(ILGenerator il, FieldInfo f, MethodInfo pack) 
        {
            il.Emit(OpCodes.Ldarg_3); // buf
            il.Emit(OpCodes.Ldloc_1, offs); // offs
            il.Emit(OpCodes.Ldloc_0, obj);
            il.Emit(OpCodes.Ldfld, f);
            il.Emit(OpCodes.Call, pack);
            il.Emit(OpCodes.Stloc_1, offs); // offs
        }

        private void generatePackMethod(ClassDescriptor desc, MethodBuilder builder)
        {
            ILGenerator il = builder.GetILGenerator();
            il.Emit(OpCodes.Ldarg_2); // obj
            il.Emit(OpCodes.Castclass, desc.cls);
            obj = il.DeclareLocal(desc.cls);
            il.Emit(OpCodes.Stloc_0, obj);
            il.Emit(OpCodes.Ldc_I4, ObjectHeader.Sizeof);
            offs = il.DeclareLocal(typeof(int));
            il.Emit(OpCodes.Stloc_1, offs);

            ClassDescriptor.FieldDescriptor[] flds = desc.allFields;

            for (int i = 0, n = flds.Length; i < n; i++)
            {
                ClassDescriptor.FieldDescriptor fd = flds[i];
                FieldInfo f = fd.field;
                switch (fd.type)
                {
                    case ClassDescriptor.FieldType.tpByte: 
                    case ClassDescriptor.FieldType.tpSByte: 
                        generatePackField(il, f, packI1);
                        continue;

                    case ClassDescriptor.FieldType.tpBoolean: 
                        generatePackField(il, f, packBool);
                        continue;
					
                    case ClassDescriptor.FieldType.tpShort: 
                    case ClassDescriptor.FieldType.tpUShort: 
                    case ClassDescriptor.FieldType.tpChar: 
                        generatePackField(il, f, packI2);
                        continue;

                    case ClassDescriptor.FieldType.tpEnum: 
                    case ClassDescriptor.FieldType.tpInt: 
                    case ClassDescriptor.FieldType.tpUInt: 
                        generatePackField(il, f, packI4);
                        continue;
					
                    case ClassDescriptor.FieldType.tpLong: 
                    case ClassDescriptor.FieldType.tpULong: 
                        generatePackField(il, f, packI8);
                        continue;
					
                    case ClassDescriptor.FieldType.tpFloat: 
                        generatePackField(il, f, packF4);
                        continue;
					
                    case ClassDescriptor.FieldType.tpDouble: 
                        generatePackField(il, f, packF8);
                        continue;
					
                    case ClassDescriptor.FieldType.tpDecimal:
                        generatePackField(il, f, packDecimal);
                        continue;

                    case ClassDescriptor.FieldType.tpGuid:
                        generatePackField(il, f, packGuid);
                        continue;

                    case ClassDescriptor.FieldType.tpDate: 
                        generatePackField(il, f, packDate);
                        continue;
					
                    case ClassDescriptor.FieldType.tpString: 
                        generatePackField(il, f, packString);
                        continue;
                
                    default:
                        il.Emit(OpCodes.Ldarg_1); // storage
                        il.Emit(OpCodes.Ldarg_3); // buf
                        il.Emit(OpCodes.Ldloc_1, offs); 
                        il.Emit(OpCodes.Ldloc_0, obj);
                        il.Emit(OpCodes.Ldfld, f);
                        il.Emit(OpCodes.Ldnull); // fd
                        il.Emit(OpCodes.Ldc_I4, (int)fd.type);
                        il.Emit(OpCodes.Ldloc_0, obj);
                        il.Emit(OpCodes.Ldarg_S, 4); // finalized
                        il.Emit(OpCodes.Call, packField);
                        il.Emit(OpCodes.Stloc_1, offs);
                        continue;
                }
            }
            il.Emit(OpCodes.Ldloc_1, offs);
            il.Emit(OpCodes.Ret);
        }

 
        private void generateUnpackMethod(ClassDescriptor desc, MethodBuilder builder)
        {
            ILGenerator il = builder.GetILGenerator();
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Castclass, desc.cls);
            LocalBuilder obj = il.DeclareLocal(desc.cls);
            il.Emit(OpCodes.Stloc_0, obj);
            il.Emit(OpCodes.Ldc_I4, ObjectHeader.Sizeof);
            LocalBuilder offs = il.DeclareLocal(typeof(int));
            il.Emit(OpCodes.Stloc_1, offs);
            LocalBuilder val = il.DeclareLocal(typeof(object));

            ClassDescriptor.FieldDescriptor[] flds = desc.allFields;

            for (int i = 0, n = flds.Length; i < n; i++)
            {
                ClassDescriptor.FieldDescriptor fd = flds[i];
                FieldInfo f = fd.field;
                if (f == null) 
                {
                    switch (fd.type)
                    {
                        case ClassDescriptor.FieldType.tpByte: 
                        case ClassDescriptor.FieldType.tpSByte: 
                        case ClassDescriptor.FieldType.tpBoolean: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpShort: 
                        case ClassDescriptor.FieldType.tpUShort: 
                        case ClassDescriptor.FieldType.tpChar: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_2);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpEnum: 
                        case ClassDescriptor.FieldType.tpInt: 
                        case ClassDescriptor.FieldType.tpUInt: 
                        case ClassDescriptor.FieldType.tpFloat: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_4);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpLong: 
                        case ClassDescriptor.FieldType.tpULong: 
                        case ClassDescriptor.FieldType.tpDate: 
                        case ClassDescriptor.FieldType.tpDouble: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_8);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpDecimal:
                        case ClassDescriptor.FieldType.tpGuid:
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4, 16);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        default:
                            il.Emit(OpCodes.Ldarg_1); // storage
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldnull); // fd
                            il.Emit(OpCodes.Ldc_I4, (int)fd.type);
                            il.Emit(OpCodes.Call, skipField);
                            il.Emit(OpCodes.Stloc_1, offs); // offs
                            continue;
                    }
                }
                else 
                {

                    switch (fd.type)
                    {
                        case ClassDescriptor.FieldType.tpByte: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldelem_U1);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpSByte: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldelem_U1);
                            il.Emit(OpCodes.Conv_I1);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpBoolean: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldelem_U1);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpShort: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackI2);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_2);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpUShort: 
                        case ClassDescriptor.FieldType.tpChar: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackI2);
                            il.Emit(OpCodes.Conv_U2);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_2);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpEnum: 
                        case ClassDescriptor.FieldType.tpInt: 
                        case ClassDescriptor.FieldType.tpUInt: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -