基础才是重中之重~Emit动态构建方法(参数和返回值)

简介:

对于Emit我们知道它的可以动态构建程序集,类型,方法,属性等,或者说只要手动使用C#创建的东西使用Emit也都可以动态创建它们,Emit由于它的特别之处,所以在很多领域得到了广泛的应用,像最近比较火的AOP技术,它最核心的功能就是方法拦截了,我们使用Emit也是可以实现方法拦截功能的,详细可以看大叔这篇文章《Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP》。

有参数,没有返回值的方法构建与调用

        [TestMethod]
        public void BulidMethod()
        {
            //得到当前的应用程序域
            AppDomain appDm = AppDomain.CurrentDomain;
            //初始化AssemblyName的一个实例
            AssemblyName an = new AssemblyName();
            //设置程序集的名称
            an.Name = "EmitLind";
            //动态的在当前应用程序域创建一个应用程序集
            AssemblyBuilder ab = appDm.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            //动态在程序集内创建一个模块
            ModuleBuilder mb = ab.DefineDynamicModule("EmitLind");
            //动态的在模块内创建一个类
            TypeBuilder tb = mb.DefineType("HelloEmit", TypeAttributes.Public | TypeAttributes.Class);
            //动态的为类里创建一个方法
            MethodBuilder mdb = tb.DefineMethod("HelloWord", MethodAttributes.Public, null, new Type[] { typeof(string) });

            //得到该方法的ILGenerator
            ILGenerator ilG = mdb.GetILGenerator();
            ilG.Emit(OpCodes.Ldstr, "Hello:{0}");
            //加载传入方法的参数到堆栈
            ilG.Emit(OpCodes.Ldarg_1);
            //调用Console.WriteLine方法,输出传入的字符
            ilG.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string), typeof(string) }));

            ilG.Emit(OpCodes.Ret);
            //创建类的Type对象
            Type tp = tb.CreateType();
            //实例化一个类
            object ob = Activator.CreateInstance(tp);
            //得到类中的方法,通过Invoke来触发方法的调用..
            MethodInfo mdi = tp.GetMethod("HelloWord");
            mdi.Invoke(ob, new object[] { "Hello Lind" });
        }

有参数,同时有返回值的方法构建与调用

        public void BulidMethodRet()
        {

            //得到当前的应用程序域
            AppDomain appDm = AppDomain.CurrentDomain;
            //初始化AssemblyName的一个实例
            AssemblyName an = new AssemblyName();
            //设置程序集的名称
            an.Name = "EmitLind";
            //动态的在当前应用程序域创建一个应用程序集
            AssemblyBuilder ab = appDm.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            //动态在程序集内创建一个模块
            ModuleBuilder mb = ab.DefineDynamicModule("EmitLind");
            //动态的在模块内创建一个类
            TypeBuilder tb = mb.DefineType("HelloEmit", TypeAttributes.Public | TypeAttributes.Class);
          
            //动态的为类里创建一个方法
            MethodBuilder mdb = tb.DefineMethod(
                "HelloWorldReturn",
                MethodAttributes.Public,
                typeof(string),
                new Type[] { typeof(string), typeof(string) });

            //得到该方法的ILGenerator
            ILGenerator ilG = mdb.GetILGenerator();
            ilG.Emit(OpCodes.Ldstr, "你好:{0}-{1}");
            //加载传入方法的参数到堆栈
            ilG.Emit(OpCodes.Ldarg_1); 
            ilG.Emit(OpCodes.Ldarg_2);
            //调用Console.WriteLine方法,输出传入的字符
            ilG.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string), typeof(string) ,typeof(string)}));

            // ilG.Emit(OpCodes.Pop);//加这个就有问题了
            //返回值部分
            LocalBuilder local = ilG.DeclareLocal(typeof(string));
            ilG.Emit(OpCodes.Ldstr, "Return Value:{0}");
            ilG.Emit(OpCodes.Ldarg_1);
            ilG.Emit(OpCodes.Call, typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(string) }));
            ilG.Emit(OpCodes.Stloc_0, local);
            ilG.Emit(OpCodes.Ldloc_0, local);
            ilG.Emit(OpCodes.Ret);
            //创建类的Type对象
            Type tp = tb.CreateType();
            //实例化一个类
            object ob = Activator.CreateInstance(tp);
            //得到类中的方法,通过Invoke来触发方法的调用..
            MethodInfo mdi = tp.GetMethod("HelloWorldReturn");
            mdi.Invoke(ob, new object[] { "Hello Lind","OK" });
        }

本文转自博客园张占岭(仓储大叔)的博客,原文链接:基础才是重中之重~Emit动态构建方法(参数和返回值),如需转载请自行联系原博主。

目录
相关文章
|
8月前
|
存储 算法 程序员
【C++20 新特性 】模板参数包展开与Lambda初始化捕获详解
【C++20 新特性 】模板参数包展开与Lambda初始化捕获详解
398 3
|
8月前
【建议】强烈推荐ES6函数自由传参的写法,针对方法体的可扩展性很有帮助
【建议】强烈推荐ES6函数自由传参的写法,针对方法体的可扩展性很有帮助
|
8月前
|
存储 C++
函数嵌套调用:C++编程的核心技术
函数嵌套调用:C++编程的核心技术
117 1
|
4月前
|
存储 前端开发 JavaScript
深度理解Promise状态变化_配合小Demo
本文通过代码示例深入探讨了JavaScript中Promise对象的三种状态(pending、rejected、resolved)及其变化过程,解释了在什么情况下Promise会从pending状态变为resolved或rejected状态,并演示了如何通过Promise的状态管理异步操作。
41 0
深度理解Promise状态变化_配合小Demo
|
6月前
|
JavaScript 前端开发 网络架构
JavaScript编码之路【对象的增强、ES6新特性之函数的默认值设置 、rest参数 (剩余参数)、拓展运算符、对象与数组的解构赋值】
JavaScript编码之路【对象的增强、ES6新特性之函数的默认值设置 、rest参数 (剩余参数)、拓展运算符、对象与数组的解构赋值】
63 1
|
8月前
|
C++
C++程序外部函数:深入理解与实践
C++程序外部函数:深入理解与实践
47 0
|
8月前
|
JavaScript 前端开发 程序员
TypeScript【枚举、联合类型函数_基础、函数_参数说明 、类的概念、类的创建】(二)-全面详解(学习总结---从入门到深化)
TypeScript【枚举、联合类型函数_基础、函数_参数说明 、类的概念、类的创建】(二)-全面详解(学习总结---从入门到深化)
52 0
|
8月前
|
小程序
小程序封装组件简单案例,所有小程序适用(传入参数、外抛事件、传入样式)
小程序封装组件简单案例,所有小程序适用(传入参数、外抛事件、传入样式)
102 0
|
前端开发 JavaScript PHP
跨域的本质-动态指定回调函数名称| 学习笔记
快速学习跨域的本质-动态指定回调函数名称。
跨域的本质-动态指定回调函数名称| 学习笔记
|
XML 前端开发 数据格式
使用 ES6 的展开运算符简化传递 props 数据的过程|学习笔记
快速学习使用 ES6 的展开运算符简化传递 props 数据的过程
145 0
使用 ES6 的展开运算符简化传递 props 数据的过程|学习笔记

热门文章

最新文章

下一篇
开通oss服务