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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WCF入门(八)——异常处理2

發布時間:2025/4/16 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WCF入门(八)——异常处理2 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

從前文中我們了解到,對于服務器端拋出的異常,WCF框架會把它封裝成FaultException返回給客戶端。系統自己封裝的FaultException攜帶的信息往往不夠,為了通知客戶端更多異常信息,需要我們在代碼中主動拋出FaultException。

????public class Service1 : IService1
????{
????????public void ErrorTest()
????????{
????????????try
????????????{
????????????????throw new InvalidOperationException("
異常測試
");
????????????}
????????????catch (Exception e)
????????????{
????????????????throw new FaultException(e.Message);
????????????}
????????}
????}

這種方式需要在所有的接口都實現,一來麻煩,而來也增加了代碼的復雜度。實際上,既然WCF框架本身就提供了封裝異常的功能,我們如果接管這個異常封裝的過程,那么就可以以一種統一的方式封裝FaultException,即能重新封裝FaultException提供詳細的錯誤信息,又不用修改服務代碼

實際上,WCF本身就提供了讓我們自己接管異常處理的接口IErrorHandler,關于的IErrorHandler處理方式和實現說明,請參看MSDN文章——IErrorHandler接口,我這里就不多介紹了,一個基本的方式如下:

????public class ErrorHandler : IErrorHandler
????{
????????public bool HandleError(Exception error)
????????{
????????????return false;
????????}

????????public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
????????{
????????????var ex = new FaultException(error.Message);
????????????var mf = ex.CreateMessageFault();
????????????fault = Message.CreateMessage(version, mf, ex.Action);
????????}
????}

ProvideFault接口里面可以實現把代碼中的異常封裝成FaultException。

在這里只是實現了這個接口,還沒有地方調用,無法生效。要使用這個接口,還需要把它和ServiceBehavior關聯起來,在IServiceBehavior對象的ApplyDispatchBehavior中關聯ErrorHanlder,一般有兩種方式:

  • Service實現IServiceBehavior接口,在代碼中顯示關聯,創建Service時則自動關聯ErrorHanlder
  • 新建對象實現IServiceBehavior接口,在配置文件中將其和Service關聯起來
  • 下面就分別介紹下這兩中實現方式:

    代碼中顯示關聯

    代碼中顯示關聯的方式比較簡單,直接在Service中實現IServiceBehavior接口即可。

    ????public class Service1 : IService1 ,IServiceBehavior
    ????{
    ????????public void ErrorTest()
    ????????{
    ????????????throw new InvalidOperationException("
    異常測試
    ");
    ????????}

    ????????#region IServiceBehavior
    成員


    ????????public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    ????????{
    ????????}

    ????????public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    ????????{
    ????????????var errorHanlder = new ErrorHandler();
    ????????????foreach (ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers)
    ????????????{
    ????????????????chanDisp.ErrorHandlers.Add(errorHanlder);
    ????????????}
    ????????}

    ????????public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    ????????{
    ????????}

    ????????#endregion
    ????}

    這種方式比較簡單,但得Service的邏輯變得復雜化,另外也不夠靈活,我們通常更多的時候使用配置文件中關聯的形式。

    配置文件中關聯

    配置文件并不能直接處理IserviceBehavior對象,它只能處理BehaviorExtensionElement對象。因此這種方式下,需要實現三個接口。

  • IErrorHandler對象中ProvideFault的函數中實現異常封裝
  • IServiceBehavior對象中實現對IErrorHandler的綁定
  • BehaviorExtensionElement對象中返回IServiceBehavior對象
  • 這里之所以分為三個接口/類,主要是為了更加靈活,像前面IErrorHandler的和IServiceBehavior就可以在直接代碼中顯示關聯的方式中使用。

    ????class ServiceBehavior : IServiceBehavior
    ????{

    ????????public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    ????????{
    ????????}

    ????????public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    ????????{
    ????????????var errorHanlder = new ErrorHandler();
    ????????????foreach (ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers)
    ????????????{
    ????????????????chanDisp.ErrorHandlers.Add(errorHanlder);
    ????????????}

    ????????}

    ????????public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    ????????{
    ????????}
    ????}

    ????public class ErrorHandlerElement : System.ServiceModel.Configuration.BehaviorExtensionElement
    ????{
    ????????protected override object CreateBehavior()
    ????????{
    ????????????return new ServiceBehavior();
    ????????}

    ????????public override Type BehaviorType
    ????????{
    ????????????get
    ????????????{
    ????????????????return typeof(ServiceBehavior);
    ????????????}
    ????????}
    ????}

    在實現時,也按照習慣自由實現幾個接口,并非一定要實現三個對象,我通常就通常將IServiceBehaviorIErrorHandler合并到一個對象中實現。

    代碼實現后,然后就需要在config文件中使用ErrorHandlerElement了。主要增加如下兩個地方的配置:

    ? ??1. 在behaviorExtensions中增加剛才寫的ErrorHandlerElement

    ? ??<extensions>
    ? ??? ??<behaviorExtensions>
    ? ??? ??? ??<add
    name="errorHanlder" type="WcfService.ErrorHandlerElement, WcfService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    ? ??? ??</behaviorExtensions>
    ? ??</extensions>

    ? ??2. 在serviceBehaviors中增加behavior(注意:這里的behavior需要是當前生效的behavior,如果不是則還需要關聯behavior)。

    ? ??<serviceBehaviors>
    ? ??? ??<behavior name="">
    ? ??? ??? ??
    <errorHanlder />
    ? ??? ??</behavior>
    ? ??</serviceBehaviors>

    配置好后,重新編譯運行,則就可以看到ErrorHanlder的效果了。

    增強異常信息

    通過上面的方法處理后,我們就可以一種通用的方式來封裝FaultException了,但由于這里是通用的方式,也存在通用方式的缺點:不能對具體異常提供細化的信息

    這個問題并不容易解決,要提供具體細化的異常信息,最靠譜的方法還是捕獲異常,封裝成FaultException<T>子類。

    不過,在文章Simplifying WCF: Using Exceptions as Faults中提供了一個通用的的序列化異常的方法,將異常序列化后傳遞到客戶端,客戶端就可以直接以像捕獲本地異常那樣捕獲遠程異常了,而不用捕獲FaultException。

    不過,這個方法也有一點問題,那就是要求客戶端也是.net語言實現的,否則其它的語言是無法反序列化CLR異常的,失去了語言無關的特性。

    轉載于:https://www.cnblogs.com/TianFang/archive/2013/01/03/2842744.html

    總結

    以上是生活随笔為你收集整理的WCF入门(八)——异常处理2的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。