C# yield在WCF中的错误用法(一)

所属分类: 软件编程 / C#教程 阅读数: 82
收藏 0 赞 0 分享

在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题。这里要说的是另一个问题:对于返回类型为IEnumerable<T>的方法来说,我们可以使用yield return的方式来输出返回集合的元素。但是如果我们不了解yield 关键字背后的实现机制,很有可能造成很大的问题。

这是一个WCF相关的问题,我想99%的人都有可能会犯这样的错误——即使你对yield了解得非常透彻。闲话少说,我们通过一个简单的实例来说明这个问题。我们定义了如下一个IDemoService接口作为服务契约,唯一的方法GetItems返回一个类型为IEnumerable<string>对象,并且具有唯一字符串参数category。

复制代码 代码如下:

  [ServiceContract]
  public interface IDemoService
  {
      [OperationContract]
      IEnumerable<string> GetItems(string category);
  }

下面是实现了该契约接口的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 http://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.”

这貌似和我们预期的效果不一样,我们希望的是客户端抛出一个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 string[] { "Foo", "Bar", "Baz" };
    }
}

再次运行我们的程序,这回可以得到我们期望的结果了。

有兴趣的朋友可以思考一下为什么两种貌似等效的方式为何会出现完全不同的结果,具体原因请看[下篇]。

更多精彩内容其他人还在看

c#开发word批量转pdf源码分享

已经安装有Office环境,借助一些简单的代码即可实现批量Word转PDF,看下面的实例源码吧
收藏 0 赞 0 分享

c# xml API操作的小例子

这篇文章主要介绍了c# xml API操作的小例子,有需要的朋友可以参考一下
收藏 0 赞 0 分享

c#唯一值渲染实例代码

这篇文章主要介绍了c#唯一值渲染实例代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

淘宝IP地址库采集器c#代码

这篇文章主要介绍了淘宝IP地址库采集器c#代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C#在后台运行操作(BackgroundWorker用法)示例分享

BackgroundWorker类允许在单独的专用线程上运行操作。如果需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用BackgroundWorker类方便地解决问题,下面看示例
收藏 0 赞 0 分享

c#文本加密程序代码示例

这是一个加密软件,但只限于文本加密,加了窗口控件的滑动效果,详细看下面的代码
收藏 0 赞 0 分享

c#生成站点地图(SiteMapPath)文件示例程序

这篇文章主要介绍了c#生成站点地图(SiteMapPath)文件的示例,大家参考使用
收藏 0 赞 0 分享

C# 键盘Enter键取代Tab键实现代码

这篇文章主要介绍了C# 键盘Enter键取代Tab键实现代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C# WinForm导出Excel方法介绍

在.NET应用中,导出Excel是很常见的需求,导出Excel报表大致有以下三种方式:Office PIA,文件流和NPOI开源库,本文只介绍前两种方式
收藏 0 赞 0 分享

C#串口通信程序实例详解

在.NET平台下创建C#串口通信程序,.NET 2.0提供了串口通信的功能,其命名空间是System.IO.Ports,创建C#串口通信程序的具体实现是如何的呢?让我们开始吧
收藏 0 赞 0 分享
查看更多