利用DynamicILInfo类动态生成方法

  ILGenerator与DynamicILInfo类是不同的。它直接使用字节数组设置IL代码,异常和本地的签名。那么,我们怎样才能获得这些字节数组从ILGenerator 与DynamicILInfo类是不同的。它直接使用字节数组设置IL代码,异常和本地的签名。那么,我们怎样才能获得这些字节数组,请看下面的代码:

using System;
using System.Reflection;
using System.Reflection.Emit;

class Demo
{
    static void Main()
    {
        DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(void), Type.EmptyTypes, typeof(Demo), false);
        DynamicILInfo il = dm.GetDynamicILInfo();

        SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper();
        il.SetLocalSignature(sigHelper.GetSignature());

        byte[] code = { 0x00, 0x72, 0x01, 0x00, 0x00, 0x70, 0x28, 0x04, 0x00, 0x00, 0x0a, 0x00, 0x2a };
        int token0 = il.GetTokenFor("Hello world");
        int token1 = il.GetTokenFor(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }).MethodHandle);
        PutInteger4(token0, 0x0002, code);
        PutInteger4(token1, 0x0007, code);
        il.SetCode(code, 8);

        dm.Invoke(null, null);       Console.Read();
    }

    static void PutInteger4(int value, int startPos, byte[] array)
    {
        array[startPos++] = (byte)value;
        array[startPos++] = (byte)(value >> 8);
        array[startPos++] = (byte)(value >> 16);
        array[startPos++] = (byte)(value >> 24);
    }
}

以下是Microsoft enginee 的解释:

If the dynamic method we are going to create is based on a static method in some existing assembly, we can view the IL code (bytes) of the static method via ildasm or by using MethodBody.GetILByteArray. We can then build the byte array for SetCode from there. For all tokens used in the original static method, be sure to replace them (bold, as shown above and below in this example) with those generated from GetTokenFor.

.method public hidebysig static void HelloWorld() cil managed
// SIG: 00 00 01
{
  // Method begins at RVA 0x2050
  // Code size 13 (0xd)
  .maxstack 8
  IL_0000: /* 00 |            
*/ nop
  IL_0001: /* 72 | (70)000001 */ ldstr "Hello world"
  IL_0006: /* 28 | (0A)000004 */ call void [mscorlib]System.Console::WriteLine(string)
  IL_000b: /* 00 |            
*/ nop
  IL_000c: /* 2A |            
*/ ret
}

To build the byte array for SetException, I‘d suggest taking a couple of minutes
to read ECMA spec partiton II (25.4.6) first. The Flags/TryOffset/TryLength/HandlerOffset/HandlerLength
... can be retrieved from MethodBody.ExceptionHandlingClauses
programatically. Be aware the exception type token (ClassToken) has to be obtained
from GetTokenFor as well. Do you know Ildasm can show the raw exception information?
I did not know this until I learned about it recently from Peli.:) Uncheck View->Expand try/catch and check show bytes; we will
see something like the following at the bottom of the method IL:

// Exception count 1

.try IL_002e to IL_0051 finally handler IL_0051 to IL_0065
  // HEX: 02 00 00 00 2E 00 00 00 23 00 00 00 51 00 00 00 14 00 00 00 00 00
00 00
}

Class SignatureHelper offers a convenient way to construct the local variable
signature, if each local variable type is known. We can just make calls of SignatureHelper.AddArgument.

Are there any scenarios in your mind where using DynamicILInfo could be better than
using DynamicILGenerator? How‘d you like to construct those byte arrays? I am thinking
about writing and sharing a tool, which, based on an existing method, generates
C# code to define the equivalent dynamic method (using DynamicILInfo) (if this turns
out to be a popular scenario).

时间: 2024-11-18 12:53:06

利用DynamicILInfo类动态生成方法的相关文章

给python类动态添加方法(method)

群里有人问如何做到 def foo(): pass class Bar(object): pass Bar.set_instance_method(foo) b = Bar() b.foo() 这个其实还是比较简单的, 只要写个函数给类设置属性即可, 可根据需求是否用函数包装下, 或者用staticmethod这个decorator: import functools def foo(): print 'hello world' class Bar(object): def __init__(s

使用runtime给类动态添加方法并调用 - class_addMethod

上手开发 iOS 一段时间后,我发现并不能只着眼于完成需求,利用闲暇之余多研究其他的开发技巧,才能在有限时间内提升自己水平.当然,“其他开发技巧”这个命题对于任何一个开发领域都感觉不找边际,而对于我来说,尝试接触 objc/runtime 不失为是开始深入探索 iOS 开发的第一步. 刚了解 runtime 当然要从比较简单的 api 开始,今天就罗列整理一下 class_addMethod 的相关点: 首先从文档开始. /** * Adds a new method to a class wi

ASM(四) 利用Method 组件动态注入方法逻辑

这篇继续结合例子来深入了解下Method组件动态变更方法字节码的实现.通过前面一篇,知道ClassVisitor 的visitMethod()方法可以返回一个MethodVisitor的实例.那么我们也基本可以知道,同ClassVisitor改变类成员一样,MethodVIsistor如果需要改变方法成员,注入逻辑,也可以通过继承MethodVisitor,来编写一个MethodXXXAdapter来实现对于方法逻辑的注入.通过下面的两个例子来介绍下无状态注入和有状态注入方法逻辑的实现.例子主要

在vue中利用vue-qr插件动态生成二维码并嵌入LOGO

收到需求要生成二维码的时候刚进项目组不久,接触vue也才一两个星期,还处于懵逼状态. 本小白的第一反应就是百度二维码的生成方法,网上有很多大神给出解决方案,最开始本小白以为是在后台生成图片然后传到前台页面,后来发现可以直接在前端用js生成,网上查到的大部分都是用jquery.qrcode.js配合utf.js(为了支持中文)和jquery-1.8.0.js来实现,亲测可行(但本白只在原生HTML中实现,vue中死活报错:"找不到qrcode方法",是不是本小白没找准姿势,哪位大神求告知

给模型类动态添加方法

想要在每个类上加个方法或者property,一种可以每个类下加,另一种如下 def get_test(self): return 1 from django.contrib.contenttypes.models import ContentType model_list = ['CommonSite'] # 或者也可以直接传类对象,下面就不用ContentType了 for obj in model_list: # ContentType.objects.get(model=obj).mode

Greenplum Database 4.3 利用mybatis框架动态生成表

1.采用mabatis3注解形式,不在采用xml配置sql方式.因为数据仓库大多用来计算,没有复杂的查询条件 mapper类注解创建表代码: package com.aicai.cepchassis.fastsampling.dao; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; public interface HttpLogTableDao { @Update(

用js动态生成css代码

有时候我们需要利用js来动态生成页面上style标签中的css代码,方法很直接,就是直接创建一个style元素,然后设置style元素里面的css代码,最后把它插入到head元素中.但有些兼容性问题我们需要解决.首先在符合w3c标准的浏览器中我们只需要把要插入的css代码作为一个文本节点插入到style元素中即可,而在IE中则需要利用style元素的styleSheet.cssText来解决.还需要注意的就是在有些版本IE中一个页面上style标签数量是有限制的,如果超过了会报错,需要考虑这点.

js动态生成css代码

用js动态生成css代码 有时候我们需要利用js来动态生成页面上style标签中的css代码,方法很直接,就是直接创建一个style元素,然后设置style元素里面的css代码,最后把它插入到head元素中.但有些兼容性问题我们需要解决.首先在符合w3c标准的浏览器中我们只需要把要插入的css代码作为一个文本节点插入到style元素中即可,而在IE中则需要利用style元素的styleSheet.cssText来解决.还需要注意的就是在有些版本IE中一个页面上style标签数量是有限制的,如果超

几何画板怎样动态生成圆锥

利用几何画板的动画效果可演示动态生态圆锥的过程,通过演示,让学生更加理解圆锥的形成过程,体会到动手实践在解决数学问题中的重要性. 利用几何画板动态生成圆锥的制作过程如下: 一.作一个虚线椭圆 二.作一个实线半椭圆 三.作圆锥的中截面 过A点作BF的垂线,在垂线上任取一个点I,连接BI和FI,得到圆锥的中截面:选中B1,调节椭圆,使其有较好的视觉效果. 四.动态生成圆锥 用鼠标选中椭圆轨迹,在其上任取一点J,连接IJ,即为动态母线:选中IJ,单击[度量]|[长度]|,得到IJ的长度:选中IJ和IJ