閱讀285 返回首頁    go 阿裏雲 go 技術社區[雲棲]


yield在WCF中的錯誤使用——99%的開發人員都有可能犯的錯誤[上篇]

在定義API的時候,對於一些返回集合對象的方法,很多人喜歡將返回類型定義成IEnumerable<T>,這本沒有什麼問題。這裏要說的是另一個問題:對於返回類型為IEnumerable<T>的方法來說,我們可以使用yield return的方式來輸出返回集合的元素。但是如果我們不了解yield 關鍵字背後的實現機製,很有可能造成很大的問題。

這是一個WCF相關的問題,我想99%的人都有可能會犯這樣的錯誤——即使你對yield了解得非常透徹。閑話少說,我們通過一個簡單的實例來說明這個問題。我們定義了如下一個IDemoService接口作為服務契約,唯一的方法GetItems返回一個類型為IEnumerable<string>對象,並且具有唯一字符串參數category。

   1:  [ServiceContract]
   2:  public interface IDemoService
   3:  {
   4:      [OperationContract]
   5:      IEnumerable<string> GetItems(string category);
   6:  }

下麵是實現了該契約接口的DemoService的實現:GetItems方法返回一個包含3個字符串的集合,但是在返回之前我們需要對參數實施驗證。如果category參數提供的字符串為Null或者是空字符串,拋出一個FaultException異常並提示“Invalid Category”,這樣客戶端在輸入不合法參數的情況下可以得到錯誤消息。這樣的編程方式再正常不過了,不是嗎?

public class DemoService : IDemoService
{
    public IEnumerable<string> GetItems(string categoty)
    {
        if (string.IsNullOrEmpty(categoty))
        {
            throw new FaultException("Invalid category");
        }
        yield return "Foo";
        yield return "Bar";
        yield return "Baz";
    }
}

可是正常並不意味著正確,客戶端其實根本無法得到服務端提供給它的錯誤消息,如下所示的是客戶端調用服務時指定一個空字符串參數情況下得到的錯誤。一個CommunicationException異常被拋出來,得到的錯誤消息為“An error occurred while receiving the HTTP response to https://127.0.0.1:3721/demoservice. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.”

image

這貌似和我們預期的效果不一樣,我們希望的是客戶端拋出一個FaultException,並提示“Invalid category”。這實際上就是因為“yield”在作祟,不相信的話可以將定義在DemoService的GetItems方法替換成如下的定義,即直接返回一個string[]對像。

public class DemoService : IDemoService
{
    public IEnumerable<string> GetItems(string categoty)
    {
        if (string.IsNullOrEmpty(categoty))
        {
            throw new FaultException("Invalid category");
        }
        return new  { "Foo", "Bar", "Baz" };
    }
}

再次運行我們的程序,這回可以得到我們期望的結果了。

image

有興趣的朋友可以思考一下為什麼兩種貌似等效的方式為何會出現完全不同的結果,具體原因請看[下篇]

yield在WCF中的錯誤使用——99%的開發人員都有可能犯的錯誤[上篇]
yield在WCF中的錯誤使用——99%的開發人員都有可能犯的錯誤[下篇]


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-25 16:04:00

  上一篇:go  一個簡易版的T4代碼生成"框架"
  下一篇:go  yield在WCF中的錯誤使用——99%的開發人員都有可能犯的錯誤[下篇]