动态创建方法和使用msil指令动态写入方法一(了解ILGenerator)

     之前讲过关于如何动态创建和使用程序集、类、方法、字段、属性等两篇文章,第一篇主要讲了介绍动态创建类型的一些基本知识和如何创建程序集、类等,第二篇主要介绍的是如何使用动态创建的程序集,调用动态创建类的方法等的一个完整DEMO。今天讲的其实也是关于在动态创建类型里,如何动态的创建一个较复杂的方法,当然今天这一篇主要着重以介绍如何ILGenerator和一些概念,下一篇就来介绍MSIL指令集。

     何为MSIL(中间语言),我想大家都可能认识它,但是完全了解它和使用它的我估计大家都要跟我一样还得继续学习MSIL。那我也就不介绍了,其实今天我要介绍的是通过ILGenerator 发出MSIL指令到MethedBuilder(方法)或者是ConstructorBuilder(构造函数)来生成方法和构造函数,其实大家可能会有一个疑问,为什么非得一定要使用MSIL来完成方法和构造函数的方法体了?

     这个原因其实主要是因为我们的程序是动态创建一个程序集,我们的方法不是生成一段代码然后动态调用编译器来完成生成一个程序集,而我们是从一开始就是使用创建程序集并向程序集里添加相应的类型,所以我们的这个程序集就必须需要实时编译的,我们需要将指令发送到(JIT编译器)的流上,没有经过如C#编译器或者是VB编译器来将代码转化为MSIL指讼。所以我们就需要动态的写入的是MSIL指令,而不是C#或者是VB.NET代码。

当然要知道如何向方法里输入MSIL指令呢?那我们就得要熟悉一些相关知识了。

System.Reflection.Emit.ILGenerator类提供可用于发出 Microsoft 中间语言 (MSIL) 的方法。ConstructorBuilder.GetILGenerator 方法为构造函数返回 ILGenerator。MethodBuilder.GetILGenerator 方法为方法返回 ILGenerator。

那么ILGenerator的主要提供那些功能呢?

1.使用 ILGenerator.Emit 方法的不同形式发出各种指令。这些指令将根据指令的类型带不同类别的操作数。(该方法将会是使用的非常多的方法)

2.ILGenerator.DefineLabel方法声明标签和ILGenerator.MarkLabel方法标记标签在MSIL流的当前位置。

3.ILGenerator.ThrowException方法用来发出引发异常的指令。

4.定义异常模块

(1)ILGenerator.BeginExceptionBlock 开始异常块。

(2)ILGenerator.BeginExceptFilterBlock 开始筛选的异常处理程序。

(3)ILGenerator.BeginCatchBlock 开始类型化异常处理程序。

(4)ILGenerator.BeginFinallyBlock 开始 finally 处理程序。

(5)ILGenerator.BeginFaultBlock 开始错误处理程序。

(6)ILGenerator.EndExceptionBlock 结束异常块。

5.定义词法范围

(1)ILGenerator.BeginScope 开始词法范围

(2)ILGenerator.EndScope 结束词法范围

6.ILGenerator.DeclareLocal定义局部变量

看下面代码列出ILGenerator常用方法的使用及演示代码,看一下就能理解了

            //通过adderBldr方法获取ILGenerator对象
            ILGenerator ilgen = adderBldr.GetILGenerator();
            Type overflow 
= typeof(OverflowException);
            ConstructorInfo exCtorInfo 
= overflow.GetConstructor(
                              
new Type[] { typeof(string) });
            
//定义局部变量
            LocalBuilder tmp1 = ilgen.DeclareLocal(typeof(int));
            LocalBuilder tmp2 
= ilgen.DeclareLocal(overflow);
            
//定义标签
            Label failed = ilgen.DefineLabel();
            Label endOfMthd 
= ilgen.DefineLabel();
            
//标记异常块开始(try)
            Label exBlock = ilgen.BeginExceptionBlock();
            
//发出MSIL指令
            ilgen.Emit(OpCodes.Ldarg_0);
            
//在当前MSIL流位置进行标记
            ilgen.MarkLabel(failed);
            
//抛出异常
            ilgen.ThrowException(overflow);
            
//声明异常块开始(Catch)
            ilgen.BeginCatchBlock(overflow);
            ilgen.Emit(OpCodes.Stloc_S, tmp2);
            ilgen.Emit(OpCodes.Ldstr, 
"Caught {0}");
            ilgen.Emit(OpCodes.Ldloc_S, tmp2);
            ilgen.Emit(OpCodes.Ldc_I4_M1);
            ilgen.Emit(OpCodes.Stloc_S, tmp1);
            
//声明异常块结束
            ilgen.EndExceptionBlock();


 今天提到的只是在动态创建方法时使用发出指令的一个帮助类,下一章我们就需要了解MSIL指令和如何输出MSIL指令的。

相关文章:

C# 动态创建和动态使用程序集、类、方法、字段等(一)

C# 动态创建和动态使用程序集、类、方法、字段等(二)

转载请标明出处: 动态创建方法和使用msil指令动态写入方法逻辑一(了解ILGenerator)

posted @ 2010-05-17 17:52  longgel  阅读(4063)  评论(5编辑  收藏  举报