日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unity AOP 处理异常的方法

發(fā)布時(shí)間:2025/3/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity AOP 处理异常的方法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
摘要

  使用 unity 處理異常的方法可能會(huì)與你的直覺不符。本文將給出正確的處理方法,并簡單剖析Unity這部分源代碼。

處理異常

  打算用Unity的AOP截獲未處理的異常,然后寫個(gè)日志什么的,于是我寫下了這樣的代碼(注意 這段代碼是錯(cuò)誤的):
public?class?MyHandler?:?ICallHandler
{
????
public?int?Order?{?get;?set;?}//?這是ICallHandler的成員,表示執(zhí)行順序???
????public?IMethodReturn?Invoke(IMethodInvocation?input,?GetNextHandlerDelegate?getNext)
????{
????????
//這之前插入方法執(zhí)行前的處理??
????????Console.WriteLine("執(zhí)行前");
????????IMethodReturn?retvalue?
=?null;
????????
try
????????{
????????????retvalue?
=?getNext()(input,?getNext);//?在這里執(zhí)行方法??
????????}
????????
catch?(Exception?ex)
????????{
????????????Console.WriteLine(
"ExMsg:"?+?ex.Message);?//?處理異常,例如寫日志之類的。
????????}
????????
//這之后插入方法執(zhí)行后的處理??
????????Console.WriteLine("完成");
????????
return?retvalue;
????}
}
為了測試一下異常有沒有被成功截獲,我讓被調(diào)用的函數(shù)拋出一個(gè)異常:
[MyHandler]
public?class?OutputImplement1?:?IOutput
{
????
public?void?Output(int?x)
????{
????????Console.WriteLine(
"執(zhí)行此方法輸出:{0}",?x);
????????
throw?new?Exception("這里拋個(gè)異常出來");
????}
}
  出人意料的是,異常并沒有被我的Catch截獲。單步執(zhí)行,可以發(fā)現(xiàn)在執(zhí)行try區(qū)塊里面的代碼時(shí)確實(shí)有異常拋出,只是catch區(qū)塊里面的代碼根本沒有執(zhí)行,然后控制臺(tái)就顯示有未處理的異常了。其實(shí),第一段代碼是錯(cuò)誤的,正確的代碼應(yīng)該像這樣:
public?class?MyHandler?:?ICallHandler
{
????
public?int?Order?{?get;?set;?}//這是ICallHandler的成員,表示執(zhí)行順序???
????public?IMethodReturn?Invoke(IMethodInvocation?input,?GetNextHandlerDelegate?getNext)
????{
????????
//這之前插入方法執(zhí)行前的處理??
????????Console.WriteLine("執(zhí)行前");
????????IMethodReturn?retvalue?
=?getNext()(input,?getNext);//在這里執(zhí)行方法??
????????if?(retvalue.Exception?==?null)?//?retvalue.Exception=null說明函數(shù)執(zhí)行時(shí)沒有拋出異常
????????{
????????????Console.WriteLine(
"執(zhí)行成功,無異常");
????????}
????????
else
????????{
????????????Console.WriteLine(
"Exxxxxx:"?+?retvalue.Exception.Message);
????????????retvalue.Exception?
=?null;?//?將retvalue.Exception設(shè)為null表示異常已經(jīng)被處理過了,
???????????????????????????????????????
//?如果不把retvalue.Exception設(shè)為null,Unity會(huì)再次拋出此異常。
????????}
????????
//這之后插入方法執(zhí)行后的處理??
????????Console.WriteLine("完成");
????????
return?retvalue;
????}
}

原因

  我百思不得其解:既然在try里面已經(jīng)執(zhí)行了OutputImplement1.Output()函數(shù),也拋出了異常,為什么catch區(qū)塊內(nèi)的代碼卻沒有被執(zhí)行呢?好在Untity是開源的,可以深入源碼一探究竟。
  找到原因后,稍稍有些失望,因?yàn)檫@原因說起來平平無奇:因?yàn)?strong>在我try之前Unity已經(jīng)try完了。也就是說,第一段代碼執(zhí)行起來會(huì)像這樣(偽代碼,加粗部分是Unity動(dòng)態(tài)生成的):
public?class?MyHandler?:?ICallHandler
{
????
public?int?Order?{?get;?set;?}//?這是ICallHandler的成員,表示執(zhí)行順序???
????public?IMethodReturn?Invoke(IMethodInvocation?input,?GetNextHandlerDelegate?getNext)
????{
????????
//這之前插入方法執(zhí)行前的處理??
????????Console.WriteLine("執(zhí)行前");
????????IMethodReturn?retvalue?
=?null;
????????
try
????????{
????????????
try
????????????{
????????????????IParameterCollection?arguments?
=?inputs.Arguments;
????????????????
this.target.Output((int)?arguments[0]);?//?在這里執(zhí)行方法,并拋出異常

????????????????retvalue?=?inputs.CreateMethodReturn(null,?new?object[]?{?arguments[0]?});
????????????}
????????????
catch
?(Exception?exception)
????????????{
????????????????retvalue?
=
?inputs.CreateExceptionMethodReturn(exception);
????????????}
????????}
????????
catch?(Exception?ex)
????????{
????????????Console.WriteLine(
"ExMsg:"?+?ex.Message);?//?處理異常,例如寫日志之類的。
????????}
????????
//這之后插入方法執(zhí)行后的處理??
????????Console.WriteLine("完成");
????????
return?retvalue;
????}
}
  當(dāng)然,上面這段代碼為了說明問題作了改寫和簡化,如果對真實(shí)的代碼感興趣可以接著往下看。

源碼剖析

類圖:
  

  藍(lán)色背景的類是我寫的演示程序中的代碼,是照著重典的教程做的。IOutPut 和 OutputImplement1相當(dāng)于業(yè)務(wù)代碼的接口和實(shí)現(xiàn)。MyHandler用來截獲對OutputImplement1里的函數(shù)的調(diào)用:
Unity AOP 演示代碼
class?Program
{
????
static?void?Main(string[]?args)
????
{
????????var?container1?
=?new?UnityContainer().AddNewExtension<Interception>().RegisterType<IOutput,?OutputImplement1>();//聲明UnityContainer并注冊IOutput???
????????container1.Configure<Interception>().SetInterceptorFor<IOutput>(new?InterfaceInterceptor());
????????IOutput?op1?
=?container1.Resolve<IOutput>();
????????op1.Output(
11);//調(diào)用
????????Console.ReadLine();
????}

}

public?interface?IOutput
{
????
void?Output(int?x);
}

[MyHandler]
public?class?OutputImplement1?:?IOutput
{
????
public?void?Output(int?x)
????
{
????????Console.WriteLine(
"執(zhí)行此方法輸出:{0}",?x);
????????
throw?new?Exception("這里拋個(gè)異常出來");
????}

}

public?class?MyHandler?:?ICallHandler
{
????
public?int?Order?{?get;?set;?}//這是ICallHandler的成員,表示執(zhí)行順序???
????public?IMethodReturn?Invoke(IMethodInvocation?input,?GetNextHandlerDelegate?getNext)
????
{
????????
//這之前插入方法執(zhí)行前的處理??
????????Console.WriteLine("執(zhí)行前");
????????IMethodReturn?retvalue?
=?getNext()(input,?getNext);//在這里執(zhí)行方法??
????????if?(retvalue.Exception?==?null)?//?retvalue.Exception=null說明函數(shù)執(zhí)行時(shí)沒有拋出異常
????????{
????????????Console.WriteLine(
"執(zhí)行成功,無異常");
????????}

????????
else
????????
{
????????????Console.WriteLine(
"Exxxxxx:"?+?retvalue.Exception.Message);
????????????retvalue.Exception?
=?null;?//?將retvalue.Exception設(shè)為null表示異常已經(jīng)被處理過了,
???????????????????????????????????????
//?如果不把retvalue.Exception設(shè)為null,Unity會(huì)再次拋出此異常。
????????}

????????
//這之后插入方法執(zhí)行后的處理??
????????Console.WriteLine("完成");
????????
return?retvalue;
????}

}

public?class?MyHandlerAttribute?:?HandlerAttribute
{
????
public?override?ICallHandler?CreateHandler(IUnityContainer?container)
????
{
????????
return?new?MyHandler();//返回MyHandler???
????}

}

  淺綠色背景的類“Wrapped_IOutput_f56a10859ef14d7794f3aa40d4eb36cc”是由Unity使用Emit在運(yùn)行期動(dòng)態(tài)創(chuàng)建的包裝類。它實(shí)現(xiàn)IOutput接口,隱式實(shí)現(xiàn)IInterceptingProxy接口。Main()函數(shù)中的“IOutput op1 = container1.Resolve<IOutput>();”實(shí)際返回的就是這個(gè)類對象。所以下一句“op1.Output(11);”執(zhí)行的是Wrapped_IOutput_f56a10859ef14d7794f3aa40d4eb36cc.Output(11)。這個(gè)函數(shù)首先將被調(diào)用函數(shù)“op1.Output(11)”的元數(shù)據(jù)(函數(shù)名、調(diào)用對象、參數(shù)等等)封裝到一個(gè)VirtualMethodInvocation對象中,然后把它作為參數(shù)傳遞給pipeline.Invoke()。pipeline.Invoke()遞歸調(diào)用所有的攔截器(即ICallHandler的實(shí)現(xiàn)類,本例中是MyHandler)的Invoke()函數(shù)。
  對OutputImplement1.Output()的調(diào)用封裝在了Wrapped_IOutput_f56a10859ef14d7794f3aa40d4eb36cc.<Output_DelegateImplementation>__0()函數(shù)中。“<Output_DelegateImplementation>__0”這個(gè)函數(shù)名看上去有些怪,那兩個(gè)“<>”符號(hào)很容易讓人感覺是泛型,但其實(shí)這就是個(gè)比較怪的函數(shù)名而已。

附錄 如何取得動(dòng)態(tài)生成的類的代碼?

  Wrapped_IOutput_f56a10859ef14d7794f3aa40d4eb36cc這個(gè)類是Unity使用Emit動(dòng)態(tài)創(chuàng)建的,所以無論看Unity的源代碼或是使用Reflector都無法取得它的源代碼。要想看它的源代碼,有兩種方法。
  第一種方法是使用Reflector的能加載運(yùn)行著的進(jìn)程的插件。但是實(shí)際上我嘗試了N多次也沒成功,總是剛剛執(zhí)行了Main()函數(shù)的第一行就報(bào)錯(cuò)。
  第二種方法是直接用Emit的AssemblyBuilder.Save()函數(shù)將動(dòng)態(tài)生成的程序集保存到硬盤上。事實(shí)上,Unity的開發(fā)人員已經(jīng)把這個(gè)代碼寫好了,就在“Microsoft Unity Application Block 1.2\UnitySource\UnitySource\Src\Unity.Interception\Interceptors\InstanceInterceptors\InterfaceInterception\InterfaceInterceptorClassGenerator.cs”的第79行:
#if?DEBUG_SAVE_GENERATED_ASSEMBLY
????assemblyBuilder.Save(
"Unity_ILEmit_InterfaceProxies.dll");
#endif我們所需要做的就是在此文件的第一行添加一句“#define DEBUG_SAVE_GENERATED_ASSEMBLY”,讓這段代碼執(zhí)行就行了。記得要重新編譯,然后讓我們的演示程序引用修改后生成的那個(gè)Microsoft.Practices.Unity.Interception.dll。再次運(yùn)行我們的演示程序,就可以在它的bin\Debug\找到名為“Unity_ILEmit_InterfaceProxies.dll”的程序集,用Reflector打開它就可以找到
類似于“Wrapped_IOutput_f56a10859ef14d7794f3aa40d4eb36cc”這樣的類了。

總結(jié)

以上是生活随笔為你收集整理的Unity AOP 处理异常的方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 三级精品在线 | 成人aaaaa| 无码精品一区二区三区在线 | 亚洲日本一区二区 | 国产人妻精品久久久久野外 | 人妻在线日韩免费视频 | 理论片午午伦夜理片影院99 | 公侵犯人妻中文字慕一区二区 | 毛片网在线观看 | 成av在线| 婷婷色中文 | 亚洲三级小说 | av一区二区三区免费观看 | 伊人伊色 | 亚洲精品69 | 操你妹影院 | 成人免费视频国产免费 | 91叼嘿视频| 日本成人高清 | 精品欧美激情精品一区 | 久久综合伊人77777麻豆最新章节 | 久久亚洲欧美 | 天堂av2014| 无码少妇一区二区三区芒果 | 色爽爽爽爽爽爽爽爽 | 亚洲视频一区二区 | 国产chinesehd精品露脸 | 国产人成在线观看 | 久久艹在线观看 | 国产人久久人人人人爽 | 欧美人与性动交a欧美精品 日韩免费高清视频 | 亚洲色图影院 | 99精品久久99久久久久 | 欧色丰满女同hd | 亚洲精品18 | 国产精品久久久久久久久免费 | 国产精品久久国产愉拍 | 黄色一级毛片 | 成人无码久久久久毛片 | 精品香蕉99久久久久网站 | 裸体一区二区三区 | 看黄网站在线观看 | 中文字幕av观看 | 天天爽天天色 | 亚洲av永久无码精品一区二区国产 | 超碰干| 午夜剧场福利 | 国产欧美日韩高清 | 丝袜美女av | 手机在线观看免费av | 国产一区二区三区免费观看 | 成年人网站免费看 | 国产主播自拍av | 国产精品女优 | 欧美日在线观看 | 国产成人免费看一级大黄 | www.蜜桃av | 2019中文字幕在线免费观看 | 日韩精品成人无码专区免费 | 93久久精品日日躁夜夜躁欧美 | 狠狠视频 | 香蕉视频免费在线看 | 男女午夜视频在线观看 | 成人免费毛片男人用品 | 波多野结衣在线观看一区二区三区 | 天天干夜夜操 | 无码少妇精品一区二区免费动态 | 国产人妻精品一区二区三区不卡 | 国内久久 | 国产又粗又长又黄的视频 | 91美女视频网站 | 青青青在线视频观看 | 风韵丰满熟妇啪啪区老熟熟女 | 免费在线观看av网站 | 91在线观| 亚洲午夜久久 | 日本高清不卡二区 | 黄色中文| 国产毛片一区 | 免费看片网站91 | 国产成人综合亚洲 | 成人夜色 | 久久人人爽人人爽 | 农村妇女一区二区 | 国产香蕉视频在线观看 | 大桥未久视频在线观看 | 欧美性猛交xxxx乱大交俱乐部 | 国产福利在线看 | 艳妇乳肉豪妇荡乳av无码福利 | www久久久天天com | av每日更新在线观看 | 国产av天堂无码一区二区三区 | 日本福利社 | 国产成人啪免费观看软件 | 婷婷爱五月天 | 一级国产精品 | exo妈妈mv在线播放高清免费 | 亚洲1区| 97国产精品人人爽人人做 |