C# Emit动态生成代码

Emit(动态方法生成)技术是一种在运行时动态生成和执行代码的技术。它的产生背景可以追溯到早期的.NET Framework版本。

在早期的.NET Framework中,开发人员通常使用反射来动态创建和执行代码。反射允许开发人员在运行时获取类型信息并调用其成员,但它的性能相对较低。每次使用反射调用方法时,都需要进行类型解析、成员查找和参数匹配等操作,这会导致一定的性能开销。

为了提高性能并提供更灵活的动态代码生成功能,微软引入了Emit技术。Emit是一个基于IL(Intermediate Language)的API,它允许开发人员直接生成IL指令并创建动态方法。通过使用Emit技术,开发人员可以在运行时生成高效且灵活的代码,并且避免了反射带来的性能开销。

Emit技术主要用于以下几个方面:

1. 动态代理:通过使用Emit技术,可以在运行时生成代理类来实现接口或继承关系的代理。这对于实现AOP(面向切面编程)和其他动态代理场景非常有用。

2. 表达式树:表达式树是一种将代码表示为对象树的方式,可以在运行时动态生成和执行代码。Emit技术可以用于创建和操作表达式树,从而实现更高级的动态代码生成和查询功能。

3. 动态代码生成:Emit技术允许开发人员在运行时生成动态方法,并直接操作IL指令。这对于需要高度灵活性和性能的场景非常有

 

下面我们要动态生成如下类

    public class MyDynamicType
    {
        public int NumberField = 0;

        public int NumberProp { get; set; }

        public MyDynamicType(int numberField)
        {
            this.NumberField = numberField;
        }

        public void ConsoleMethod()
        {
            Console.WriteLine("欢迎来到高级班学习");
        }


        public int MyMethod(int para)
        {
            return 2 * para;
        }
    }

Emit 动态生成type

            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynamicAssemblyExample"), AssemblyBuilderAccess.RunAndCollect);

            // 对于单个模块程序集,模块名称通常为;程序集名称加上扩展名。  
            ModuleBuilder modulebuilder = assemblyBuilder.DefineDynamicModule("MyModal"); //托管模块
            TypeBuilder typebuilder = modulebuilder.DefineType("MyDynamicType", TypeAttributes.Public);
            Type type= typebuilder.CreateType();

Emit 定义字段、构造函数

            // 在Type中生成公有字段
            FieldBuilder fieldBuilder = typebuilder.DefineField("NumberField", typeof(int), FieldAttributes.Public);

            // 定义一个接受整数参数的构造函数,储存在public区域。  
            Type[] parameterTypes = { typeof(int) };
            ConstructorBuilder ctor1 = typebuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, parameterTypes);

Emit动态生成构造函数

            //中间语言的生成者
            ILGenerator ctor1IL = ctor1.GetILGenerator();

            //对于构造函数,参数0是对新 
            //实例。在调用base之前将其推到堆栈上 
            //类构造函数。指定的默认构造函数 
            //通过传递 
            //类型(Type.EmptyTypes)到GetConstructor。 

            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

            //在推送参数之前,先将实例推送到堆栈上 
            //将被分配给私有字段m\u编号。 
            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Ldarg_1);
            ctor1IL.Emit(OpCodes.Stfld, fieldBuilder);
            ctor1IL.Emit(OpCodes.Ret);

Emit动态生成方法

            MethodBuilder consoleMethod = typebuilder.DefineMethod("ConsoleMethod", MethodAttributes.Public | MethodAttributes.Static, null, null);
            ILGenerator consoleMethodIL = consoleMethod.GetILGenerator();
            consoleMethodIL.Emit(OpCodes.Ldstr, "欢迎来到高级班第15期进阶学习");
            consoleMethodIL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
            consoleMethodIL.Emit(OpCodes.Ret); //写IL最后一定要Ret


            MethodBuilder AddMethod = typebuilder.DefineMethod("AddMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(int), typeof(int) });
            ILGenerator AddMethodIL = AddMethod.GetILGenerator();
            AddMethodIL.Emit(OpCodes.Ldarg_0);
            AddMethodIL.Emit(OpCodes.Ldarg_1);
            AddMethodIL.Emit(OpCodes.Add_Ovf_Un);
            AddMethodIL.Emit(OpCodes.Ret);

 

posted @ 2022-09-04 18:19  明志德道  阅读(320)  评论(0编辑  收藏  举报