• 动态方法与动态代理(上篇)


    所谓动态方法,是指在程序运行阶段生成的并且能够执行的方法. 动态方法可以关联到任何已有的模块(Module)中,作为现有模块的扩展. 动态方法可以访问模块中所有类型及其成员.  

    实现动态方法依赖于:反射发出(System.Reflection.Emit)、 MSIL语言  

    •微软中间语言(MSIL)是将.Net代码转化为机器语言的一个中间过程。它是一种介于高级语言和汇编语言的伪汇编语言,也是.Net框架的基础,任何高级应用都是在其之上发展起来的。尽管2.0之后,微软相继推出的各个版本都包含很多新的功能,但MSIL语言却基本上没有发生变化,可谓是“万变不离其宗”,了解MSIL语言是实现动态方法的前提,千里之行始于足下
    •.Net自带的查看MSIL的工具:ILDASM

      String.ToLower()方法的MSIL代码

    •基本语法

    操作指令

    说明

    ldarg

    将参数加载到堆栈顶部

    例如:ldarg.0 将第一个参数加载到堆栈

    starg 

    将栈顶元素保存到参数

    例如:starg.0 将栈顶数据保存到第一个参数

    ldloc  

    将本地变量加载到堆栈顶部

    例如:ldloc.0 将第一个变量加载到堆栈

    stloc  

    将栈顶元素保存到本地变量

    例如:stloc.0 将栈顶数据保存到第一个变量

    ldc

    将常量数字加载到堆栈顶部

    例如:ldc.i4.2 将2加载到堆栈,i4表示int32数字

    类似的还有用于加载字符串的ldstr、加载和保存字段的ldfld和stfld、加载数字常量的ldc等等,这些指令执行的操作很好记,以ld开头的就是加载到堆栈,以st开头的就是从堆栈上取回值

    call

    callvirt

    作用都是调用方法,但用法有区别:call用于执行非虚函数或静态方法;callvirt用于执行虚函数或实例方法,注意,这里所说的是一般情况,编译器为了优化也有例外。

     

    ret

    方法返回,如果有返回值,则将其从被调者堆栈转移到调用者堆栈顶部

    nop

    空操作

    br

    无条件跳转,br.s是br的短格式

    例如:br.s L_0002 无条件跳转到L_0002行

    brtrue

    操作数非空或非False时跳转

    例如:brtrue.s L_0002 当操作数为真时跳转到L_0002行

    brfalse

    操作数为空、为False或为0时跳转

    例如:brfalse.s L_0002 当操作数为假时跳转到L_0002行

    相关的跳转语言还有beq、bge、ble和blt等等,执行跳转语言后,堆栈元素将被清除,即堆栈顶部不包含元素,b和br都是branch的缩写  

    add

    将两个操作数相加,结果放到堆栈顶部

    sub

    将两个操作数相减,结果放到堆栈顶部

    •反射发出 

    反射发出不是将文本形式的C#代码编译成DLL

        •使用IL语言动态的产生可执行代码
        •相关类位于System.Reflection.Emit命名空间中
        •反射发出创建的是MSIL代码,而不是产生源代码
        •IL操作指令包含在OpCodes中
     
    •Demo:动态方法演示
        class Program
        {
            
    static void Main(string[] args)
            {
                Type[] paramTypes 
    = new Type[] { typeof(string) };

                DynamicMethod hello 
    = new DynamicMethod("Hello"null, paramTypes, typeof(Program).Module);
                ILGenerator ilGen 
    = hello.GetILGenerator();
                ilGen.Emit(OpCodes.Ldarg_0);

                MethodInfo writeLineMethod 
    = typeof(Console).GetMethod("WriteLine"new Type[] { typeof(string) });

                ilGen.Emit(OpCodes.Call, writeLineMethod);

                ilGen.Emit(OpCodes.Ret);

                Action
    <string> invoker = (Action<string>)hello.CreateDelegate(typeof(Action<string>));

                invoker(
    "你好,我来自于动态方法");
            }
        }

     

  • 相关阅读:
    Qt编程之右键单击QTreeWidgetItem弹出菜单
    Qt编程之QString 处理换行
    配置zbar识别二维码(转载)
    我学习图像处理的小结
    自己动手,实现“你的名字”滤镜
    结合grabcut和inpaint,实现人像去除
    (转载)找圆算法((HoughCircles)总结与优化
    寻找白板上的便签条
    寻找精密光学标定板上的矩形(网友提问)
    OpenCV中Denoising相关函数的简单介绍
  • 原文地址:https://www.cnblogs.com/dubing/p/2087035.html
Copyright © 2020-2023  润新知