C# yield在WCF中的错误用法(一)
作者:junjie 发布时间:2022-06-05 06:36:57
在定义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" };
}
}
再次运行我们的程序,这回可以得到我们期望的结果了。
有兴趣的朋友可以思考一下为什么两种貌似等效的方式为何会出现完全不同的结果,具体原因请看[下篇]。


猜你喜欢
- 一、匿名结构体struct{ char name[20]; int age;}s1;匿名
- 前言Android中类加载器有BootClassLoader,URLClassLoader,PathClassLoader,DexClass
- 在Windows平台上,播放PCM声音使用的API通常有如下两种。waveOut and waveIn:传统的音频MMEAPI,也是使用的最
- SpringCloud @FeignClient 参数详解今天因为工作中遇到FeignClient一个奇葩的bug,后面仔细研究了,找出了原
- DAO模式是接口的一个典型应用。1. StudenDaoListImpl.java与StudentDaoArrayImpl.java有何不同
- 本文介绍了Android是如何设置组件半透明和透明的效果,分享出来供大家参考,下面来看看详细的介绍:1、Button或者ImageButto
- 1.使用WINDOWS API/// <summary> /// 判断一个磁盘驱动器的类型 /// </summary&g
- 方法一:使用多个controller的共同拥有的父类,即精确到两个controller的上一级@Beanpublic Docket crea
- 需求描述一个五子棋游戏,能实现双方黑白对决,当一方获胜时给出提示信息,利用GUI界面实现项目结构如下图一、实体FiveChess类提供五子棋
- 本文实例讲述了C#编程实现动态改变配置文件信息的方法。分享给大家供大家参考,具体如下:配置文件实际上就是一个XML文件,所以我们可以使用Xm
- 相应的类库可在我的资源页面中找到,关于类成员的说明可通过对象浏览器查看函数说明Imports BitOperatorLibrary.Shif
- classpath读取resources目录下文件最近在springboot+maven的项目中去读取资源文件的时候,报了找不到文件的错误。
- 大白话讲解:从广义上 Spring 注解可以分为两类:一类注解是用于注册 Bean假如 IoC 容器是一间空屋子,首先这间空屋子啥都没有,我
- 在我们将Winform自带的边框隐藏之后,我们需要自己编写窗口的移动。思路就是1.获得点击左键时当前鼠标的坐标2.获得移动后鼠标的坐标3.窗
- SpringAOP的介绍:传送门demo介绍主要通过自定义注解,使用SpringAOP的环绕通知拦截请求,判断该方法是否有自定义注解,然后判
- 因为某些需求,要在特定的时间执行一些任务,比如定时删除服务器存储的数据缓存,定时获取数据以及定时发送推送等等,这时就需要用到定时任务了。定时
- 一、什么是 LRU 算法就是一种缓存淘汰策略。计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置。但问题是,删除哪些内容呢?
- WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数
- 概要集合概念:像数组一样是java的一个容器;和数组不同的是数组只能存同类型的数据,且长度定义之后就不可变,集合不仅,可以存多种类型的数据,
- 环境搭建创建Maven项目。pom.xml文件中引入RocketMQ依赖。<dependencies>