Emit的简单用法

// 安装 System.Reflection.Emit
// 工具:ILSpy
using System;
using System.Reflection;
using System.Reflection.Emit;

            // 首先申明程序集名称
            AssemblyName assemblyName = new AssemblyName("MyAssembly");

            // 获取程序集构造器
            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

            // 通过程序集获取模块构造器
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModule");

            // 通过模块获取类型构造器
            // public class MyType { }
            TypeBuilder typeBuilder = moduleBuilder.DefineType("MyType", TypeAttributes.Public);
            //typeBuilder.DefineTypeInitializer(); // 静态构造函数

            #region 动态生成静态方法
            /*
             * public static void MyMethodForSayHello()
             * {
             *      Console.WriteLine("Hello, jieke");
             *      Console.ReadLine();
             * }
             */
            {
                // 通过类型获取方法构造器
                MethodBuilder methodBuilder = typeBuilder.DefineMethod("MyMethodForSayHello", MethodAttributes.Public | MethodAttributes.Static, null, null);

                // 通过方法获取IL生成器
                ILGenerator ilGenerator = methodBuilder.GetILGenerator();

                // 通过IL定义方法体
                ilGenerator.Emit(OpCodes.Ldstr, "Hello, jieke"); // 载入字符串
                ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod(nameof(Console.WriteLine), new Type[] { typeof(string) })); // 输出字符串到控制台
                ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod(nameof(Console.ReadLine))); // 从控制台读取一行输入
                ilGenerator.Emit(OpCodes.Pop); // 将读取到的数据从栈顶弹出
                ilGenerator.Emit(OpCodes.Ret); // 函数返回 
            }
            #endregion

            #region 生成带参数和返回值得的实例方法
            /*
             * public int Add(int x, int y)
             * {
             *      return x + y;
             * }
             */
            {
                Type returnType = typeof(int);
                Type[] parameterTypes = new Type[] { typeof(int), typeof(int) };

                // 通过类型获取方法构造器
                MethodBuilder methodBuilder = typeBuilder.DefineMethod("Add", MethodAttributes.Public | MethodAttributes.HideBySig, returnType, parameterTypes); // 定义函数申明
                methodBuilder.DefineParameter(1, ParameterAttributes.None, "x"); // 定义第一个参数
                methodBuilder.DefineParameter(2, ParameterAttributes.None, "y"); // 定义第二个参数

                // 通过方法获取IL生成器
                ILGenerator ilGenerator = methodBuilder.GetILGenerator();

                // 定义本地变量
                LocalBuilder local1 = ilGenerator.DeclareLocal(typeof(int));

                ilGenerator.Emit(OpCodes.Nop);

                // 通过IL定义方法体
                ilGenerator.Emit(OpCodes.Ldarg_1); // 载入索引为1的参数
                ilGenerator.Emit(OpCodes.Ldarg_2); // 载入索引为2的参数
                ilGenerator.Emit(OpCodes.Add); // 执行两数相加
                ilGenerator.Emit(OpCodes.Stloc_0); // 将栈顶的数据弹出放到本地变量列表索引为零的变量上
                ilGenerator.Emit(OpCodes.Ldloc_0); // 将本地变量列表索引为零的变量上的值放到计算堆栈上
                ilGenerator.Emit(OpCodes.Ret); // 函数返回 
            }
            #endregion

            #region 定义字段
            FieldBuilder fieldName;
            FieldBuilder fieldAge;
            {
                // private string _name = string.Empty;
                fieldName = typeBuilder.DefineField("_name", typeof(string), FieldAttributes.Private);
                //fieldName.SetConstant(string.Empty);

                // private string _age = 18;
                fieldAge = typeBuilder.DefineField("_age", typeof(int), FieldAttributes.Private);
                //fieldAge.SetConstant(18);
            }
            #endregion

            #region 定义属性
            {
                // public string Name { get { return this._name; } set { this._name = value; } }
                {
                    MethodBuilder methodGetName = typeBuilder.DefineMethod("GetName", MethodAttributes.Public, typeof(string), null);
                    MethodBuilder methodSetName = typeBuilder.DefineMethod("SetName", MethodAttributes.Public, null, new Type[] { typeof(string) });

                    ILGenerator iLGeneratorForGetName = methodGetName.GetILGenerator();
                    iLGeneratorForGetName.Emit(OpCodes.Ldarg_0); // 载入当前实例,this
                    iLGeneratorForGetName.Emit(OpCodes.Ldfld, fieldName); // 载入字段
                    iLGeneratorForGetName.Emit(OpCodes.Ret); // 返回

                    ILGenerator iLGeneratorForSetName = methodSetName.GetILGenerator();
                    iLGeneratorForSetName.Emit(OpCodes.Ldarg_0); // 载入当前实例,this
                    iLGeneratorForSetName.Emit(OpCodes.Ldarg_1); // 载入第一个参数
                    iLGeneratorForSetName.Emit(OpCodes.Stfld, fieldName); // 将栈顶的数据设置到字段上
                    iLGeneratorForSetName.Emit(OpCodes.Ret); // 返回

                    PropertyBuilder propertyName = typeBuilder.DefineProperty("Name", PropertyAttributes.None, CallingConventions.HasThis, typeof(string), null);
                    propertyName.SetGetMethod(methodGetName);
                    propertyName.SetSetMethod(methodSetName);
                }

                // public int Age { get { return this._age; } set { this._age = value; } }
                {
                    MethodBuilder methodGetAge = typeBuilder.DefineMethod("GetAge", MethodAttributes.Public, typeof(int), null);
                    MethodBuilder methodSetAge = typeBuilder.DefineMethod("SetAge", MethodAttributes.Public, null, new Type[] { typeof(int) });

                    ILGenerator iLGeneratorForGetAge = methodGetAge.GetILGenerator();
                    iLGeneratorForGetAge.Emit(OpCodes.Ldarg_0); // 载入当前实例,this
                    iLGeneratorForGetAge.Emit(OpCodes.Ldfld, fieldAge); // 载入字段
                    iLGeneratorForGetAge.Emit(OpCodes.Ret); // 返回

                    ILGenerator iLGeneratorForSetAge = methodSetAge.GetILGenerator();
                    iLGeneratorForSetAge.Emit(OpCodes.Ldarg_0); // 载入当前实例,this
                    iLGeneratorForSetAge.Emit(OpCodes.Ldarg_1); // 载入第一个参数
                    iLGeneratorForSetAge.Emit(OpCodes.Stfld, fieldAge); // 将栈顶的数据设置到字段上
                    iLGeneratorForSetAge.Emit(OpCodes.Ret); // 返回

                    PropertyBuilder propertyAge = typeBuilder.DefineProperty("Age", PropertyAttributes.None, CallingConventions.HasThis, typeof(int), null);
                    propertyAge.SetGetMethod(methodGetAge);
                    propertyAge.SetSetMethod(methodSetAge);
                }
            }
            #endregion

            #region 定义构造函数
            {
                /*
                 public MyType(string name, int age) { this._name = name; this._age = age; }
                 */
                {
                    Type objectType = Type.GetType("System.Object");
                    ConstructorInfo objectCtor = objectType.GetConstructor(Array.Empty<Type>());

                    Type[] constructorArgs = { typeof(string), typeof(int) };
                    ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorArgs);
                    ILGenerator iLGeneratorForConstructor = constructorBuilder.GetILGenerator();

                    iLGeneratorForConstructor.Emit(OpCodes.Ldarg_0); // 载入当前对象
                    iLGeneratorForConstructor.Emit(OpCodes.Call, objectCtor); // 调用父类构造函数

                    iLGeneratorForConstructor.Emit(OpCodes.Ldarg_0); // 载入当前对象
                    iLGeneratorForConstructor.Emit(OpCodes.Ldarg_1); // 载入第一个参数
                    iLGeneratorForConstructor.Emit(OpCodes.Stfld, fieldName); // 将第一个参数的值设置到_name field上

                    iLGeneratorForConstructor.Emit(OpCodes.Ldarg_0); // 载入当前对象
                    iLGeneratorForConstructor.Emit(OpCodes.Ldarg_2); // 载入第二个参数
                    iLGeneratorForConstructor.Emit(OpCodes.Stfld, fieldAge); // 将第二个参数的值设置到_age field上

                    iLGeneratorForConstructor.Emit(OpCodes.Ret);
                }

                /*
                 public MyType() { }
                 */
                {
                    Type objectType = Type.GetType("System.Object");
                    ConstructorInfo objectCtor = objectType.GetConstructor(Array.Empty<Type>());
                    ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
                    ILGenerator iLGeneratorForConstructor = constructorBuilder.GetILGenerator();

                    iLGeneratorForConstructor.Emit(OpCodes.Ldarg_0); // 载入当前对象
                    iLGeneratorForConstructor.Emit(OpCodes.Call, objectCtor); // 调用父类构造函数
                    iLGeneratorForConstructor.Emit(OpCodes.Ret);
                }
            }
            #endregion

            #region 覆写父类的ToString方法
            {
                MethodBuilder methodToString = typeBuilder.DefineMethod("ToString", MethodAttributes.Virtual | MethodAttributes.Public, typeof(string), null);
                ILGenerator iLGenerator = methodToString.GetILGenerator();

                var local = iLGenerator.DeclareLocal(typeof(string)); // 创建本地变量
                iLGenerator.Emit(OpCodes.Ldstr, "Name: [{0}], Age: [{1}]"); // 载入字符串模版
                iLGenerator.Emit(OpCodes.Ldarg_0); // 载入当前对象,this
                iLGenerator.Emit(OpCodes.Ldfld, fieldName); // 载入_name field
                iLGenerator.Emit(OpCodes.Ldarg_0); // 载入当前对象,this
                iLGenerator.Emit(OpCodes.Ldfld, fieldAge); // 载入_age field
                iLGenerator.Emit(OpCodes.Box, typeof(int)); // 将值类型装箱为object
                iLGenerator.Emit(OpCodes.Call, typeof(string).GetMethod(nameof(string.Format), new Type[] { typeof(string), typeof(object), typeof(object) }));
                iLGenerator.Emit(OpCodes.Stloc, local); // 弹出栈顶的值并存储到变量中
                iLGenerator.Emit(OpCodes.Ldloc, local); // 将变量的值载入到栈顶
                iLGenerator.Emit(OpCodes.Ret); // 函数返回
            }
            #endregion

            //typeBuilder.DefineInitializedData("_name", Encoding.Unicode.GetBytes("empty"), FieldAttributes.Private);
            //typeBuilder.DefineInitializedData("_age", BitConverter.GetBytes(18), FieldAttributes.Private);

            // 生成类型
            Type myType = typeBuilder.CreateType();

            // 使用动态生成的类型
            #region 使用静态方法
            {
                dynamic staticInstance = new StaticMembersDynamicWrapper(myType);
                staticInstance.MyMethodForSayHello();
            }
            #endregion
            #region 使用实例方法
            {
                dynamic instance = Activator.CreateInstance(myType);
                dynamic result = instance.Add(1, 1);
                instance.Age = 10;
                Console.WriteLine(instance);
                instance.Name = "jieke";
                Console.WriteLine(instance.Name);
            }
            #endregion
            #region 使用有参构造函数、属性及ToString方法
            {
                dynamic instance = Activator.CreateInstance(myType, "jieke", 20);
                Console.WriteLine(instance);

                instance.Age++;
                instance.Age = instance.Age + 1;

                PropertyInfo ageProperty = myType.GetProperty("Age");
                int age = ageProperty.GetValue(instance);
                age++;
                ageProperty.SetValue(instance, age);

                Console.WriteLine(instance);
            }
            #endregion
// 秒懂C#通过Emit动态生成代码 https://www.cnblogs.com/gaochundong/archive/2013/06/01/csharp_emit_generate_assembly.html
// C#使用Emit生成构造函数和属性 https://www.cnblogs.com/gaochundong/archive/2013/06/01/csharp_emit_create_constructor_properties.html
// C#使用Emit构造拦截器动态代理类 https://www.cnblogs.com/gaochundong/archive/2013/06/01/csharp_emit_create_interceptor_proxy.html
// c# dynamic 类型调用静态方法实例 https://blog.csdn.net/weixin_34332905/article/details/90153259
// 说说emit(中)ILGenerator https://www.cnblogs.com/xuanhun/archive/2012/06/22/2558698.html
// IL指令集 https://wenku.baidu.com/view/143ab58a6529647d27285234.html
// Emit学习(2) - IL - 值类型和引用类型(补) https://www.cnblogs.com/elvinle/p/6015097.html
// Emit学习(3) - OpCodes - 动态添加属性、构造函数、方法 https://www.cnblogs.com/elvinle/p/6007536.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值