本来准备直接进入Dapper的, 但是昨天初步看了一下, 内容不少, Dapper不愧是一款成熟的框架, 里面对各种情况的考虑, 很实用, 不过这也使得我短时间内看不完, 所以得等几天了.

那就先来看看循环和异常吧, 看IL跳转的时候, 有一个标签, 跳来跳去的, 在OpCodes里面, 也是有对应的实现的.

一、示例

public static void Xunhuan(int num)
{
try
{
int sum = ;
if (num < )
{
throw new Exception("num is less than 1");
}
for (int i = ; i <= num; i++)
{
sum += i;
}
Console.WriteLine("executed successfully : Sum = " + sum);
}
catch (Exception e)
{
Console.WriteLine("error happened : " + e.Message);
}
}

在调用Xunhuan()的时候, 传入小于1的值时, 会抛出异常, 进入异常处理部分,  否则进入循环(此处为了演示, 使用循环, 否则应该使用算法计算结果), 求和. 结果我就不贴了.

二、OpCodes实现

static Action<int> action;
static void Main(string[] args)
{
//定义一个动态方法
var method = new DynamicMethod("Xunhuan", null, new Type[] { typeof(int) });
ILGenerator IL = method.GetILGenerator(); //定义标签
var label1 = IL.DefineLabel();
var xunLabel = IL.DefineLabel();
var endLabel = IL.DefineLabel(); //定义本地变量
var sum = IL.DeclareLocal(typeof(int));
var i = IL.DeclareLocal(typeof(int)); IL.Emit(OpCodes.Ldc_I4_0);
IL.Emit(OpCodes.Stloc_0); //sum = 0 IL.Emit(OpCodes.Ldc_I4_1);
IL.Emit(OpCodes.Stloc_1); // i = 1
IL.Emit(OpCodes.Ldstr, "enter number : num = ");
IL.Emit(OpCodes.Ldarg_0);
//实现方式一 装箱
IL.Emit(OpCodes.Box, typeof(int)); //装箱
IL.Emit(OpCodes.Call, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(object) }));
IL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); Label tryLabel = IL.BeginExceptionBlock(); //try
IL.Emit(OpCodes.Ldarg_0); //num
IL.Emit(OpCodes.Ldc_I4_1); //
IL.Emit(OpCodes.Bge, label1); //num >= 1 -> label1, 注: try里面的跳转, 不能跳出try语句, 只能在内部 IL.Emit(OpCodes.Ldstr, "num is less than 1");
IL.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) })); //new Exception();
IL.Emit(OpCodes.Throw); //throw IL.MarkLabel(label1);
IL.Emit(OpCodes.Ldloc_1); //i
IL.Emit(OpCodes.Ldarg_0); //num
IL.Emit(OpCodes.Bgt, xunLabel); // i > num -> endLabel IL.Emit(OpCodes.Ldloc_0);
IL.Emit(OpCodes.Ldloc_1);
IL.Emit(OpCodes.Add);
IL.Emit(OpCodes.Stloc_0); // sum += i; IL.Emit(OpCodes.Ldloc_1);
IL.Emit(OpCodes.Ldc_I4_1);
IL.Emit(OpCodes.Add);
IL.Emit(OpCodes.Stloc_1); //i+=1;
IL.Emit(OpCodes.Br_S, label1); IL.MarkLabel(xunLabel);
IL.Emit(OpCodes.Ldstr, "executed successfully : Sum = ");
IL.Emit(OpCodes.Ldloc_0);
//实现方式二 调用Convert.ToString(int num)方法
IL.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToString", new Type[] { typeof(int) }));
IL.Emit(OpCodes.Call, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }));
IL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) })); IL.MarkLabel(endLabel);
IL.Emit(OpCodes.Nop); IL.BeginCatchBlock(typeof(Exception)); //catch
IL.Emit(OpCodes.Callvirt, typeof(Exception).GetMethod("get_Message"));
IL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
IL.EndExceptionBlock(); //end IL.Emit(OpCodes.Ret); action = (Action<int>)method.CreateDelegate(typeof(Action<int>)); //此处通过委托的方式来调动方法, 而不再是保存成dll文件了 Console.WriteLine("-------------正常执行---------------");
action.Invoke();
Console.WriteLine("-------------异常执行---------------");
action.Invoke(-);
Console.ReadKey();
}

实现的方式并不是唯一的, 我写的这个方法, 并不是最简的. 下面贴出reflector反编译的IL代码, 与我写的这个还是有不少不同的.

   .method public hidebysig static void Xunhuan(int32 num) cil managed
{
.maxstack
.locals init (
[] int32 num2,
[] int32 num3,
[] class [mscorlib]System.Exception exception,
[] bool flag)
L_0000: nop
L_0001: nop
L_0002: ldc.i4.
L_0003: stloc.
L_0004: ldarg.
L_0005: ldc.i4.
L_0006: clt
L_0008: ldc.i4.
L_0009: ceq
L_000b: stloc.
L_000c: ldloc.
L_000d: brtrue.s L_001b
L_000f: nop
L_0010: ldstr "num is less than 1"
L_0015: newobj instance void [mscorlib]System.Exception::.ctor(string)
L_001a: throw
L_001b: ldc.i4.
L_001c: stloc.
L_001d: br.s L_0029
L_001f: nop
L_0020: ldloc.
L_0021: ldloc.
L_0022: add
L_0023: stloc.
L_0024: nop
L_0025: ldloc.
L_0026: ldc.i4.
L_0027: add
L_0028: stloc.
L_0029: ldloc.
L_002a: ldarg.
L_002b: cgt
L_002d: ldc.i4.
L_002e: ceq
L_0030: stloc.
L_0031: ldloc.
L_0032: brtrue.s L_001f
L_0034: ldstr "executed successfully : Sum = "
L_0039: ldloc.
L_003a: box int32
L_003f: call string [mscorlib]System.String::Concat(object, object)
L_0044: call void [mscorlib]System.Console::WriteLine(string)
L_0049: nop
L_004a: nop
L_004b: leave.s L_0068
L_004d: stloc.
L_004e: nop
L_004f: ldstr "error happened : "
L_0054: ldloc.
L_0055: callvirt instance string [mscorlib]System.Exception::get_Message()
L_005a: call string [mscorlib]System.String::Concat(string, string)
L_005f: call void [mscorlib]System.Console::WriteLine(string)
L_0064: nop
L_0065: nop
L_0066: leave.s L_0068
L_0068: nop
L_0069: ret
.try L_0001 to L_004d catch [mscorlib]System.Exception handler L_004d to L_0068
}

以前总是懒, 对于新的知识, 都是看看, 看懂就成, 但是在实际写的过程中, 会碰到很多看不会遇到的问题, 编码还真不是看看就能写好的, 好记性不如烂笔头, 还是得自己一行一行敲一下, 才能发现里面的问题.

Emit学习(3) - OpCodes - 循环和异常的更多相关文章

  1. Emit学习(3) - OpCodes - 动态添加属性、构造函数、方法

    上一篇介绍了 IL 的部分, 基础的部分, 暂时就介绍到那里了, 接下来要进入代码编写阶段了. 今天的主题是 在代码运行的过程中, 去动态的创建类, 属性, 方法. 来源:http://www.cnb ...

  2. System.Reflection.Emit学习

    C#反射发出System.Reflection.Emit学习 分享: 1 一.System.Reflection.Emit概述 Emit,可以称为发出或者产生.与Emit相关的类基本都存在于Syste ...

  3. python入门学习:9.文件和异常

    python入门学习:9.文件和异常 关键点:文件.异常 9.1 从文件中读取数据9.2 写入文件9.3 异常9.4 存储数据 9.1 从文件中读取数据 9.1.1 读取整个文件  首先创建一个pi_ ...

  4. Python学习 Part6:错误和异常

    Python学习 Part6:错误和异常 两种不同类型的错误:语法错误和异常 1. 语法错误 语法错误,也被称作解析错误: >>> while True print('Hello w ...

  5. plsql分支,循环,异常

    pl/sql 分支,循环和异常分支:    DECLARE        BEGIN        END; 循环:loop,while,for    1.LOOP        EXIT WHEN ...

  6. 《python基础教程(第二版)》学习笔记 语句/循环/条件(第5章)

    <python基础教程(第二版)>学习笔记 语句/循环/条件(第5章) print 'AB', 123 ==> AB 123 # 插入了一个空格print 'AB', 'CD' == ...

  7. JavaSE学习笔记(6)---异常

    JavaSE学习笔记(6)---异常 ​ 软件程序在运行过程中,非常可能遇到问题,我们称之为异常,英文是:Exception,意思是例外.遇到这些例外情况,或者叫异常,我们怎么让写的程序做出合理的处理 ...

  8. Emit学习(2) - IL - 常用指令介绍

    学习Emit必不可少的, 会使用到IL中间代码. 初见IL代码, 让我有一种汇编的感觉, 让我想起了, 大学时, 学习8051的汇编语言. 多的就不扯了, 直接进入正题, OpCodes指令集是不是有 ...

  9. Emit学习(1) - HelloWorld

    之前看过Dapper(使用到了Emit), CYQ.Data(另一种思路,没有使用Emit)类的框架之后, 也想自己做一个小框架玩一下, 不过此时能力太过欠缺, 做不了Cyq.Data或者PDF.Ne ...

随机推荐

  1. 走进AngularJs(九)表单及表单验证

    年底了越来越懒散,AngularJs的学习落了一段时间,博客最近也没更新.惭愧~前段时间有试了一下用yeoman构建Angular项目,感觉学的差不多了想做个项目练练手,谁知遇到了一系列问题.yeom ...

  2. SQL SERVER--DBA 常用到的一些脚本

    自己整理了一些常用到的脚本,希望对各位有用 下载地址 --================================== 妹子不能少,是吧 BTW, 妹子是我辛苦百度来的,请不要求种求介绍各种求 ...

  3. 为什么我的新项目选择了Quick-cocos2d-x

    混Quick社区快一周了,还是决定分享一下我选择Quick的原因. 一是向大家介绍一下我自己,同时也希望给大家提供一个参考首先,向大家介绍一下我自己姓名,年龄,性别这些都不重要了.我是一名程序员,在游 ...

  4. 使用JSSDK集成微信分享遇到的一些坑

    h5项目中需要集成微信分享,以实现自定义标题.描述.图片等功能.结果遇到了很多坑. 准备工作 务必详细阅读微信JS-SDK说明文档 需要后端支持 强烈建议下载使用微信web开发者工具 按文档配置好公众 ...

  5. fir.im Weekly - 从零开始创建 Android 新项目

    今年的 Google I/O 大会上,人工智能和虚拟现实的产品发布让我们对未来多了几分惊喜.对于开发者部分,Google 发布了 Android N 系统,感受最深的是全新的 Android Stud ...

  6. 过滤器中的chain.doFilter(request,response)

    Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml文件配置好要 ...

  7. javascript_core_01之数据类型与运算

    1.数据类型转换: ①隐式转换:程序根据需要,自动转化数据类型: ②强制转换:主动调用函数执行转换: 2.字符串强制转换: ①x.toString():不能转换null和undefined: ②Str ...

  8. 通过Class获取标签,兼容的几种思路

    在js中通过document.getElementsByClassName()在低版本IE浏览器中不兼容.然后我写了几种方案,大家可以参考参考. html代码 <!DOCTYPE html> ...

  9. SQL Server 2014云特性:无缝集成公有云

    本篇是我在IT168的约稿,原文地址:http://tech.it168.com/a2014/0620/1637/000001637358_all.shtml       IT行业已经进入了云时代,未 ...

  10. CSS 框模型( Box module )

    框和布局 在 KB005: CSS 层叠 中已经介绍了 CSS 的重要之处.CSS 可以说是页面表现的基础, CSS 可以控制布局,控制元素的渲染. 布局是讲在电影画面构图中,对环境的布置.人物地位的 ...