異常處理在程序中也算是比較重要的一部分了,IL異常處理在C#裡面實現會用到一些新的方法
1.BeginExceptionBlock:異常塊代碼開始,相當於try,但是感覺又不太像
2.EndExceptionBlock:異常塊代碼結束,BeginExceptionBlock相當於try,EndExceptionBlock卻不是try結束。而是整個異常塊處理的結束。
3.BeginCatchBlock:catch塊代碼
4.BeginFinallyBlock:finally塊代碼
5.ThrowException:拋出異常
下面我們就通過代碼來實現一下。
一、異常信息捕捉
首先我們做一個簡單的異常捕捉,然後輸出對應的異常信息,首先給出C#代碼:
int translationInt = 0; try { translationInt = Convert.ToInt32(translationStr); } catch (Exception ex) { Console.WriteLine(ex.Message); } return translationInt;View Code
實現代碼也比較簡單
string name = "IL4.Dynamic"; string fileName = string.Format("{0}.dll", name); //構建程序集 AssemblyName assemblyName = new AssemblyName(name); //應用程序集域 AppDomain domain = AppDomain.CurrentDomain; //實例化一個AssemblyBuilder對象來實現動態程序集的構建 AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); //定義模塊(不加filename為瞬態模塊,不持久) ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name, fileName); //定義類型 TypeBuilder typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public); MethodBuilder methodbuilder = typeBuilder.DefineMethod("ExceptionTest", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(string) }); ILGenerator IL = methodbuilder.GetILGenerator(); LocalBuilder translationInt = IL.DeclareLocal(typeof(Int32)); Type translationException = typeof(Exception); ConstructorInfo constructorInfo = translationException.GetConstructor(new Type[] { typeof(string) }); MethodInfo exToString = translationException.GetMethod("ToString"); IL.Emit(OpCodes.Ldc_I4_0); IL.Emit(OpCodes.Stloc_0); Label tryLabel = IL.BeginExceptionBlock(); IL.Emit(OpCodes.Ldarg_1); IL.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) })); IL.Emit(OpCodes.Stloc_0); IL.BeginCatchBlock(typeof(Exception)); IL.EmitCall(OpCodes.Callvirt, exToString, null); IL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); IL.EndExceptionBlock(); IL.Emit(OpCodes.Ldloc_0); IL.Emit(OpCodes.Ret);View Code
二、拋出異常
程序中有時候,不僅要捕捉異常信息,有時候也是需要拋出對應的異常信息,throw new Exception("translation Exception");這時候就需要用到ThrowException,代碼如下:
IL.Emit(OpCodes.Ldstr, "translation Exception"); IL.Emit(OpCodes.Newobj, constructorInfo); IL.ThrowException(typeof(newException)); IL.Emit(OpCodes.Ldstr, "20"); IL.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) })); IL.Emit(OpCodes.Stloc_0); IL.EmitCall(OpCodes.Callvirt, exToString, null); IL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));View Code
1.IL.Emit(OpCodes.Newobj, constructorInfo):相當於是一個 new Exception("translation Exception");
2.不過在這一步有一個疑點, IL.ThrowException(typeof(newException));是不會把異常信息"translation Exception"拋出,而在對應的操作IL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));卻能輸出這部分的異常信息。可以看下反編譯後的代碼
三、finally處理
finally實現也是比較簡單的,直接上代碼把
IL.BeginFinallyBlock(); IL.Emit(OpCodes.Ldstr, "10"); IL.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) })); IL.Emit(OpCodes.Stloc_0); IL.EmitWriteLine("Finally"); IL.EndExceptionBlock();View Code
異常處理這塊msdn寫得也比較清楚,我也不多說了,示例代碼ExceptionDemo