2012-10-16 60 views
2

在我的WCF服務上,我有幾個自定義錯誤類型。一個抽象的類型,稱爲BaseFault和它的兩個實現所謂TypeOneFault和TypeTwoFault捕獲多個自定義FaultException類型

我拋出異常在服務端這樣

public string ThisMethodHasFault(string eType) 
{ 
    if (eType.Contains("One")) 
    { 
     TypeOneFault one = new TypeOneFault("TypeOneFault thrown"); 
     throw new FaultException<TypeOneFault>(one, new FaultReason(new FaultReasonText("Fault reason here"))); 
    } 
    else 
    { 
     TypeTwoFault two = new TypeTwoFault("TypeTwoFault thrown"); 
     throw new FaultException<TypeTwoFault>(two, new FaultReason(new FaultReasonText("Fault reason here"))); 
    } 

    return ""; 
} 

我的服務接口是這樣

[OperationContract] 
[FaultContract(typeof(TypeOneFault))] 
[FaultContract(typeof(TypeTwoFault))] 
string ThisMethodHasFault(string eType); 

在客戶端我有一個測試winform應用程序,我在這裏看到它

MyServiceClient client = new MyServiceClient(); 

    try 
    { 
     client.ThisMethodHasFault(""); //get value from user 

    } 
    catch (FaultException<TypeOneFault> ox) 
    { 
     TypeOneFault oneEx = ox.Detail; 
     oneEx.{property} ... 

    } 
    catch (FaultException<TypeTwoFault> tx) 
    { 
     TypeTwoFault twoEx = tx.Detail; 
     twoEx.{property} ... 
    }  

問:

我似乎能夠通過這樣做是爲了減少catch塊的數量,而不是

catch (FaultException<BaseFault> fex) 
    { 
     BaseFault Ex = fex.Detail; 
     twoEx.{property} ... 
    }  

這本來是很高興有這樣一個塊,可以捕獲任何異常我扔在服務器上,通過抽象我得到正確的課程的細節。通過這樣做,我得到一個錯誤。 An unhandled exception of type 'System.ServiceModel.FaultException 1'發生在mscorlib.dll'

有什麼我需要改變,使這項工作,或者我必須滿足多個catch塊只?從FaultException

+0

我編輯了你的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。此外,與論壇網站不同,我們不使用「謝謝」或「任何幫助表示讚賞」,或在[so]上簽名。請參閱「[應該'嗨','謝謝',標語和致敬從帖子中刪除?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be - 刪除 - 從帖子)。 –

回答

4

FaultException<T>繼承,這樣你就可以趕上基類型來代替:

catch(FaultException ex) { 
    if(ex is FaultException<TypeOneFault>) { 
     var detail = ((FaultException<TypeOneFault>) ex).Detail; 
     // process it 
    } else if(ex is FaultException<TypeTwoFault>) { 
     var detail = ((FaultException<TypeTwoFault>) ex).Detail; 
     // process it 
    } else { 
     // unexpected error 
     throw; 
    } 
} 

不同的是兩個獨立的catch塊,這可重構:

catch(FaultException ex) { 
     if(!ProcessFault(ex)) { 
      throw; 
     } 

bool ProcessFault(FaultException ex) { 
    if(ex is FaultException<TypeOneFault>) { 
     var detail = ((FaultException<TypeOneFault>) ex).Detail; 
     // process it 
     return true; 
    } else if(ex is FaultException<TypeTwoFault>) { 
     var detail = ((FaultException<TypeTwoFault>) ex).Detail; 
     // process it 
     return true; 
    } else { 
     // unexpected error 
     return false; 
    } 
} 

如果兩種故障類沒有關係,那就是儘可能遠。但是,如果從一個共同的基礎繼承,那麼你就可以進一步重構:

bool ProcessFault(FaultException ex) { 
    if(ex is FaultException<TypeOneFault>) { 
     ProcessFault(((FaultException<TypeOneFault>) ex).Detail); 
     return true; 
    } else if(ex is FaultException<TypeTwoFault>) { 
     ProcessFault(((FaultException<TypeTwoFault>) ex).Detail); 
     return true; 
    } else { 
     // unexpected error 
     return false; 
    } 
} 

void ProcessFault(BaseFault detail) { 
    // process it 
} 
+1

這就像有多個catch塊一樣,我必須分別評估每個異常。 – user20358

+0

它只是儘可能多的代碼行,但一個catch塊更容易處理你可以將這些內容重構爲一個單獨的方法來啓動 –

+1

更新了我認爲你想要的答案 –

2

如何這樣的事情,使用FastMember爲了方便,但你可以使用動態和一些try/catch塊獲得同樣的效果:

try 
{ 
    client.ThisMethodHasFault(""); 
} 
catch (FaultException e) 
{ 
    var accessor = TypeAccessor.Create(e.GetType()); 
    var detail = accessor.GetMembers().Any(x => x.Name == "Detail") 
        ? accessor[e, "Detail"] as BaseFault 
        : null; 

    if (detail != null) 
    { 
     // Do processing here 
    } 
    else 
    { 
     throw; 
    } 
} 
相關問題