本帖介绍怎么在 WCF 中,在 Server-side 和 Client-side 之间,传递默认无法传输的 List<T>、List<自定义类> 等类型的对象,以及传递 Dictionary 等泛型 Collection 对象。本帖并无高来高去的高深技术,但版工我认为本帖的小技巧实用性很高,而且是每个学习 WCF 的人都一定会遇到的问题,因此斗胆将本文发在博客园首页。

--------------------------------------------------------
本帖的示例下载点:
http://files.cnblogs.com/WizardWu/090809.zip

执行示例需要 Visual Studio 2008 + SP1,不需要数据库。
若您下载后,在 VS 2008 里按 F5 时项目无法正常执行,请留言告知。
--------------------------------------------------------

在编程时,DataSet、DataTable,以及 List、Dictionary 等 Collection 类型常会使用到。在 .NET
Web Service 和 WCF 中,服务器端函数 (Operation) 的返回类型,若为
DataSet、DataTable,则客户端可直接调用 (若客户端程序也是 .NET 的话);但在 WCF 中,VS 2008
默认的配置,并无法传输 List<string>、List<自定义类> 等类型的对象,而泛型的 Dictionary
对象却可以。

[注:Method、Operation 中文都叫做「方法」,但前者是存在 OO 中的类,不存在网络上;后者存在于 Service 中,公开在网络上可供其他程序调用。WCF、Data Services 和 RIA Services 中公开在网络上的函数和方法,都可称作 Operation。]

关于这点,小弟我查了微软 MCTS 认证 WCF 3.5 的官方用书 [10]、O'Reilly 的书籍
[11],都未提到如何解决,书中只提到 .NET collections 的 metadata,以 WSDL 在网络上传输时,会以「数组
(array)」的格式呈现。

Because .NET collections are .NET-specific, WCF cannot expose them in the service metadata, yet because they are so useful, WCF offers dedicated marshaling rules for collections.

Whenever you define a service operation that uses the collection
interfaces IEnumerable<T>, IList<T>, or
ICollection<T>, the specific collection-type information gets lost
in the metadata (WSDL) export, so in terms of how collection types are
sent across the wire, they all are represented as arrays, the resulting metadata always uses an array.

开发 WCF 时,若 VS 2008 都用默认配置,则当 WCF 的服务器端函数 (Operation) 的返回类型为
List<string> 时,实际返回的类型为 string[] 数组,因此客户端若仍用 List<string>
的变量去接收和赋值时,在编译时期,即会发生下图 1 的转型错误:

List 数据结构反序列化后,在客户端自动变成了数组

后来我在网络上发现两篇博文 [1], [2],提到只要更改 VS 2008 中,WCF 客户端程序「添加服务引用 (Add Service Reference)」的设置即可处理此种需求。做法如下:

请参阅本帖的下载示例。当我们的客户端程序,要引用网络上既有的 WCF 服务契约时,我们会如下图 2 般,添加一个 service proxy reference。
在 ASP.NET 客户端程序中引用 WCF Service

在下图 3 的「添加服务引用」窗体中,右上方的「前往」按钮,是要查看网络上某个 IP 和端口的 WCF
Service;右边的「发现」按钮,是要查看和此客户端项目,位于同一个 VS 2008 解决方案里的 WCF
Service。此时我们单击窗体左下方的「高级」按钮。
在此窗格里输入正确的元数据交换地址,会自动取得 WCF Service 的 Operation 名称

如下图 4,我们在「集合类型」下拉菜单中,把默认的 System.Array 改成我们想使用的 Generic.List
类型;而另一个「字典集合类型」下拉菜单则保持不变,表示此 WCF Service 可在网络上传输泛型的 Dictionary 类型对象。

默认的集合类型为 System.Array

微软的 VS 默认会这样设置,可能如同博文 [2] 所提到的,WCF 的客户端可能是旧版 .NET 1.x 版的环境,也可能是
Java 或其他各种非微软的技术平台,因此 VS 2008 默认选用所有厂商、所有平台都支持的 Array 数组,作为网络传输的类型,而非最新版
.NET 平台特有的 Collection 数据结构。

最后,若用户端程序要再更改配置,只要如下图 5 般,在 VS 项目里既有的 Reference 上,选择「配置服务引用」即可。

在 ASP.NET 客户端程序中,修改已引用的 WCF Service

以下为本帖下载示例的代码。我们在服务器端的 WCF Service,提供三个返回类型分别为
List<string>、List<自定义类>、Dictionary<string,string>
的函数,给 WCF 客户端 ASP.NET 程序调用,执行结果如下图 6。

Server-side/IService.cs
Server-side/Service.cs

Client-side/Default.aspx.cs


public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ServiceReference1.ServiceClient prox = new ServiceReference1.ServiceClient();         /*********** List<string> ***********/
        //string[] list1 = new string[2];   //未改设置前,Server 返回的 List<string>,Client 只能取得 string 数组
        List<string> list1 = new List<string>();        
        list1 = prox.getListString();         Response.Write(list1[] + "<br>");
        Response.Write(list1[] + "<p>");         /*********** List<自定义类> ***********/
        List<ServiceReference1.Employee> list2 = new List<ServiceReference1.Employee>();
        list2 = prox.getListEmployee();
        
        Response.Write(list2[].name + "<br>");
        Response.Write(list2[].age + "<br>");
        Response.Write(list2[].oooo + "<p>");      //object 类型         /*********** Dictionary<string,string> ***********/
        Dictionary<string, string> dict1 = new Dictionary<string, string>();
        dict1 = prox.getDictionaryString();         foreach (KeyValuePair<string, string> kvp in dict1)
        {
            Response.Write(kvp.Key + ", " + kvp.Value + "<br>");
        }
    }
}

本帖示例执行结果,从 WCF Service 返回 List<string>、List<自定义类>、泛型 Dictionary 三种类型的变量

WCF 笔记 (2) - 传输泛型 List 对象的更多相关文章

  1. WCF入门教程(四)通过Host代码方式来承载服务 一个WCF使用TCP协议进行通协的例子 jquery ajax调用WCF,采用System.ServiceModel.WebHttpBinding System.ServiceModel.WSHttpBinding协议 学习WCF笔记之二 无废话WCF入门教程一[什么是WCF]

    WCF入门教程(四)通过Host代码方式来承载服务 Posted on 2014-05-15 13:03 停留的风 阅读(7681) 评论(0) 编辑 收藏 WCF入门教程(四)通过Host代码方式来 ...

  2. WCF学习笔记之传输安全

    WCF学习笔记之传输安全 最近学习[WCF全面解析]下册的知识,针对传输安全的内容做一个简单的记录,这边只是简单的记录一些要点:本文的内容均来自[WCF全面解析]下册: WCF的传输安全主要涉及认证. ...

  3. C# WCF学习笔记(二)终结点地址与WCF寻址(Endpoint Address and WCF Addressing) WCF中的传输协议

    URI的全称是 Uniform Rosource Identifire(统一资源标识),它唯一标识一个确定的网绐资源,同时也表示资源所处的位置及访问的方式(资源访问所用的网络协议). 对于Endpoi ...

  4. 菜鸟学习WCF笔记-Address

    终结点是WCF最为核心的对象,因为它承载了所有通信功能.服务通过相应的终结点发布出来,客户端通过与之匹配的终结点对服务进行调用.终结点有地址.绑定和契约ABC三要素构成. Address  作为终结点 ...

  5. WCF分布式开发步步为赢(4):WCF服务可靠性传输配置与编程开发

    今天继续WCF分布式开发步步为赢系列的第4节:WCF服务可靠性传输配置与编程开发.这个章节,我们要介绍什么是WCF服务的可靠性传输,随便介绍网络协议的概念,Web Service为什么不支持可靠性传出 ...

  6. <数据结构与算法分析>读书笔记--利用Java5泛型实现泛型构件

    一.简单的泛型类和接口 当指定一个泛型类时,类的声明则包括一个或多个类型参数,这些参数被放入在类名后面的一对尖括号内. 示例一: package cn.generic.example; public ...

  7. WCF大文件传输【转】

    http://www.cnblogs.com/happygx/archive/2013/10/29/3393973.html WCF大文件传输 WCF传输文件的时候可以设置每次文件的传输大小,如果是小 ...

  8. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  9. 使用Fiddler解析WCF RIA Service传输的数据

    原文 http://www.cnblogs.com/wintersun/archive/2011/01/05/1926386.html 使用Fiddler 2 解析WCF RIA Service传输的 ...

随机推荐

  1. 理解JavaScript设计模式与开发应用中发布-订阅模式的最终版代码

    最近拜读了曾探所著的<JavaScript设计模式与开发应用>一书,在读到发布-订阅模式一章时,作者不仅给出了基本模式的通用版本的发布-订阅模式的代码,最后还做出了扩展,给该模式增加了离线 ...

  2. 10款很酷的HTML5动画和实用应用 有源码

    10款很酷的HTML5动画和实用应用,这里有菜单.SVG动画.Loading动画,总有你喜欢的,而且,每一款HTML5应用都提供源代码下载,方便大家学习和研究,一起来看看吧. 1.HTML5 SVG ...

  3. Model Builder中Table2Table中字段映射的问题

    ArcGIS10中使用过程中,Bug不少.尽管有了SP3,但模型耦合的深层次的应用中还是错误不少.目前只是遇到一个,利用躲避的方法解决一个.例如,从NetCDF中抽出的数据表,必须在内存和数据库中都存 ...

  4. [NOIP2014]解方程

    3732 解方程  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 输入描述 Input Descrip ...

  5. 如何在DOS下用C/C++ 编译器

    本文来自CSDN博客     ★★ 注意:以下适合 PC 环境 ★★   ●C/C++ 编译器需要的环境变数设定     古早以来,PC 上的 C 编译器,就需要两个环境变数:     LIB:这个环 ...

  6. VS默认环境设置

    VS2010的工具菜单-->导入导出设置-->重置所有设置

  7. Amazon Kinesis Producer Library 使用记录

    Amazon Kinesis 是一种托管的服务,用于有弹性与扩展性的实时处理大规模的流数据.该服务收集大数据记录流,多个可在 Amazon EC2 实例上运行的数据处理应用程序随后可实时使用此流. 在 ...

  8. php ftp文件上传函数--新手入门参考

    在 php编程中,用ftp上传文件比较多见,这里分享个简单入门型的ftp上传实例. <?php /** * ftp上传文件 * 学习ftp函数的用法 */ // 定义变量 $local_file ...

  9. SVM入门

    前言: 又有很长的一段时间没有更新博客了,距离上次更新已经有两个月的时间了.其中一个很大的原因是,不知道写什么好-_-,最近一段时间看了看关于SVM(Support Vector Machine)的文 ...

  10. Java String.split()注意点

    //String[] aa = "aaa|bbb|ccc".split("|");//错误 String[] aa = "aaa|bbb|ccc&qu ...