.NET(C#):Emit建立異常處理的方法

來源:互聯網
上載者:User

目錄

Emit異常處理流程
顯示Exception對象的Message屬性
返回目錄
Emit異常處理流程
來看這種C#異常處理代碼:

複製代碼 代碼如下: static void doo(Exception e)

{

try

{

throw e;

}

catch (ApplicationException ex)

{

Console.WriteLine("捕獲ApplicationException");

}

catch

{

Console.WriteLine("捕獲Exception");

}

finally

{

Console.WriteLine("finally塊");

}

}

我們將用反射Emit建立一個這樣的方法。

其實IL中的異常處理代碼還是比較複雜的,你可以在Reflector下看看異常處理的IL代碼。不過好在ILGenerator類提供了一些方便的方法來建立異常處理代碼。

基本套路就是用如下ILGenerator的方法:

BeginExceptionBlock方法來開始異常處理代碼(相當於try)。
之後的代碼可以用Opcodes.Throw來拋出異常,或者調用其他可以拋出異常的代碼。
接著用BeginCatchBlock方法來開始一個Catch塊,該方法可以指定catch需要捕獲的異常類型,另外有一點需要注意的是凡是進入該catch方法,邏輯棧上會有相應類型的異常對象。 同時,這裡也可以用Opcodes.Rethrow來重新拋出異常。
最後BeginFinallyBlock方法開始一個finally塊。 (這裡不需要手動加Opcodes.Leave)
當全部異常處理代碼寫完後,加上EndExceptionBlock方法來結束整塊異常處理代碼塊。
注意方法最後還是必須要加IL的ret指令的(Opcodes.Ret),否則CLR無法運行此方法。

來看代碼:

複製代碼 代碼如下: //+ using System.Reflection;

//+ using System.Reflection.Emit;

static void Main(string[] args)
{
var dm = GetMethod();

dm.Invoke(null, new object[] { new ApplicationException() });

dm.Invoke(null, new object[] { new Exception() });

}
static DynamicMethod GetMethod()

{

var dm = new DynamicMethod("", null, new Type[] { typeof(Exception) });

var ilgen = dm.GetILGenerator();

//try {

ilgen.BeginExceptionBlock();

//載入第一個參數,並throw

ilgen.Emit(OpCodes.Ldarg_0);

ilgen.Emit(OpCodes.Throw);

ilgen.BeginCatchBlock(typeof(ApplicationException));

//清空棧上的異常對象

ilgen.Emit(OpCodes.Pop);

ilgen.EmitWriteLine("捕獲ApplicationException");

ilgen.BeginCatchBlock(typeof(Exception));

//清空棧上的異常對象

ilgen.Emit(OpCodes.Pop);

ilgen.EmitWriteLine("捕獲Exception");

ilgen.BeginFinallyBlock();

ilgen.EmitWriteLine("finally塊");

//結束整個處理塊

ilgen.EndExceptionBlock();

ilgen.Emit(OpCodes.Ret);

return dm;

}

輸出:

複製代碼 代碼如下:捕獲ApplicationException

finally塊

捕獲Exception

finally塊

返回目錄
顯示Exception對象的Message屬性
上面的代碼並沒有顯示Exception對象的Message屬性,上面主要是介紹Emit異常處理的流程,下面來看看怎樣顯示Message屬性,如果是直接輸出當然簡單了,不過如果用到Console.WriteLine的格式字串的話,需要在catch代碼塊中用一個臨時變數。

如下代碼:

複製代碼 代碼如下: //+ using System.Reflection;

//+ using System.Reflection.Emit;
static void Main(string[] args)
{
var dm = GetMethod();

dm.Invoke(null, new object[] { new Exception("來自Mgen!") });
}

static DynamicMethod GetMethod()
{

var dm = new DynamicMethod("", null, new Type[] { typeof(Exception) });

var ilgen = dm.GetILGenerator();

//try {

ilgen.BeginExceptionBlock();

//載入第一個參數,並throw

ilgen.Emit(OpCodes.Ldarg_0);

ilgen.Emit(OpCodes.Throw);

ilgen.BeginCatchBlock(typeof(Exception));

//臨時變數 和 需要的反射資訊

var exp = ilgen.DeclareLocal(typeof(Exception));

var msg = typeof(Exception).GetProperty("Message").GetGetMethod();

var output = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string), typeof(object) });

//儲存異常對象到臨時變數exp

ilgen.Emit(OpCodes.Stloc, exp);

//格式字串進棧

ilgen.Emit(OpCodes.Ldstr, "錯誤資訊: {0}");

//載入臨時變數

ilgen.Emit(OpCodes.Ldloc, exp);

//擷取Message屬性

ilgen.Emit(OpCodes.Callvirt, msg);

//調用有格式字串的Console.WriteLine

ilgen.Emit(OpCodes.Call, output);

//結束整個處理塊

ilgen.EndExceptionBlock();

ilgen.Emit(OpCodes.Ret);

return dm;

}

輸出:

複製代碼 代碼如下:錯誤資訊: 來自Mgen!
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.