• MSIL实用指南-生成异常处理



    本篇讲解怎么生成异常。C# 异常处理时建立在四个关键词之上的:try、catch、finally 和 throw。

    一、异常的抛出
    抛出异常在C#语言中要使用throw关键字,使用方法是
    throw <一个异常对象>;

    throw;

    1、抛出异常
    抛出异常的指令是Throw,它对应的C#使用语句是
    throw new <异常类型>;

    它的使用格式是
    adderIL.ThrowException(<异常Type>);

    它的生成步骤是
    (1)用newobj指令创一个异常对象
    (2)生成Throw指令

    2、再次抛出异常
    抛出异常的指令是Rethrow,它对应的C#语句是
    throw;
    这条语句只有一个关键字“throw”和封号,所以它只能用在catch语句块,是把捕捉到的异常再次抛出。

    二、异常的处理
    C#语言的异常处理是try...catch...finally语句。
    它的生成步骤是

    1.用DefineLabel创建一个异常处理结束的标签。

    2、生成try
    这要使用BeginExceptionBlock方法,返回一个Label对象。

    3、生成catch
    这要使用BeginCatchBlock方法,有一个参数,它代表所要捕捉的异常类型。
    实例:
    ilGenerator.BeginCatchBlock(typeof(ArgumentNullException));

    4、生成finally
    这要使用BeginFinallyBlock方法。

    5、结束异常
    这要使用EndExceptionBlock方法。

    6、标记异常处理结束


    完整程序:

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace LX1_ILDemo
    {
        class Demo26_TryCatchFinally
        {
            static string binaryName = "Demo26_TryCatchFinally.exe";
            static string namespaceName = "LX1_ILDemo";
            static string typeName = "DemoTryCatchFinally";
    
            static AssemblyBuilder assemblyBuilder;
            static ModuleBuilder moduleBuilder;
            static TypeBuilder typeBuilder;
            static MethodBuilder mainMethod;
            static MethodBuilder testMethod;
    
            static void Emit_TestMethod()
            {
                testMethod = typeBuilder.DefineMethod("Test", MethodAttributes.Public
                   | MethodAttributes.Static, typeof(void), new Type[] { typeof(string)});
                ILGenerator ilGenerator = testMethod.GetILGenerator();
    
                Label endOfMethodLabel = ilGenerator.DefineLabel();
    
                Label exceptionBlock = ilGenerator.BeginExceptionBlock();
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Call, typeof(int).GetMethod("Parse", new Type[] { typeof(string) }));
                ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }));
                //ilGenerator.Emit(OpCodes.Leave_S, endOfMethodLabel);
    
                ilGenerator.BeginCatchBlock(typeof(ArgumentNullException));
                ilGenerator.Emit(OpCodes.Pop);
                ilGenerator.EmitWriteLine("error");
                ilGenerator.Emit(OpCodes.Rethrow);
                //ilGenerator.Emit(OpCodes.Leave_S, endOfMethodLabel);
    
                ilGenerator.BeginFinallyBlock();
                ilGenerator.EmitWriteLine("finally");
                MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
                ilGenerator.Emit(OpCodes.Call, readKeyMethod);
                ilGenerator.Emit(OpCodes.Pop);
    
                ilGenerator.EndExceptionBlock();
    
                ilGenerator.MarkLabel(endOfMethodLabel);
                ilGenerator.Emit(OpCodes.Ret);
            }
             
            public static void Generate()
            {
                InitAssembly();
                typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public);
    
                Emit_TestMethod();
                GenerateMain();
    
                assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
                SaveAssembly();
                Console.WriteLine("生成成功");
            }
    
            static void GenerateMain()
            {
                mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
                    | MethodAttributes.Static, typeof(void), new Type[] { });
                var ilGenerator = mainMethod.GetILGenerator();
                ilGenerator.Emit(OpCodes.Ldstr,"10t");
                ilGenerator.Emit(OpCodes.Call, testMethod);
         
                MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
                ilGenerator.Emit(OpCodes.Call, readKeyMethod);
                ilGenerator.Emit(OpCodes.Pop);
    
                ilGenerator.Emit(OpCodes.Ret);
            }
    
            static void InitAssembly()
            {
                AssemblyName assemblyName = new AssemblyName(namespaceName);
                assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
                moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
            }
    
            static void SaveAssembly()
            {
                Type t = typeBuilder.CreateType(); //完成Type,这是必须的
                assemblyBuilder.Save(binaryName);
            }
        }
    }
    View Code
  • 相关阅读:
    vijosP1360-八数码问题
    android——卡片式布局
    android ——悬浮按钮及可交互提示
    android ——滑动菜单
    android ——Toolbar
    android ——多线程编程
    android ——调用摄像头拍照和相册
    android ——通知管理
    android——实现跨程序访问数据
    android——SQLite数据库存储(操作)
  • 原文地址:https://www.cnblogs.com/tkt2016/p/8795853.html
Copyright © 2020-2023  润新知