WCF中的集合类型

在.net中,各种类型的集合均实现了IEnumerable或者IEnumerable<T>接口,一个数据契约的数据成员可以是一个集合类型,服务契约也可以定义直接与集合交互的操作,但是这都是.net所特有的,WCf不能在元数据中公开它们,然后WCF专门为集合提供了编组原则。

     在定义服务时候,无论使用的是IEnumerable<T>、IList<T>和ICollection<T>,他们的传输形式都使用了数组,如

namespace ContractInterface

{

    [ServiceContract]

public interface IContractManager

    {

        [ OperationContract]

IEnumerable<Contract> GetContracts();

    }

}

导出的结果为

public interface IContractManager

{

Contract[] GetContracts();

    }

如果契约中的集合为具体集合类型而非接口,而且属于可序列化集合,那么只要提供的集合包含了Add方法,并且符合以下签名中的一种,WCF就能够自动地将集合规范为数组类型。

     并非只有内建的集合类型才具有自动编组为数组的能力,任何自定义的集合只要符合相同的先决条件,都可以被编组为数组。

CollectionDataContract特性

前面所示的编组为具体类型的机制并不理想,原有有三

  1. 它要求集合必须可序列化,而不是使用DataContract特性。
  2. 当服务的一方处理集合类型时,服务的另外一方若处理数组类型,就会导致双方语义不对称,集合拥有数组不具备的优势。
  3. 对于集合是否包含Add方法,或者集合是否支持IEnumerable和IEnumerable<T>接口,并没有编译时或者运行时的有效验证。如果不符合条件,就会导致数据契约不可工作。

基于以上几点,WCF提供了另外一种有效的解决方案,一种专用的特性:CollectionDataContractAttribute,定义为:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false , AllowMultiple = false)]

public sealed class CollectionDataContractAttribute : Attribute

    {

public CollectionDataContractAttribute();

public bool IsReference { get; set; }

public string ItemName { get; set; }

public string KeyName { get; set; }

public string Name { get; set; }

public string Namespace { get; set; }

public string ValueName { get; set; }

    }

CollectionDataContract和DataContract相似,它不能序列化集合,将它应用到一个集合上时,会将集合当作一个泛型的链表类型公开给客户端链表可能不会对原来的集合执行任何操作,但它会提供一个类似接口的集合类型,而不是数组。例如,定义如下类型:

namespace ContractInterface

{

    [CollectionDataContract(Name= "MyCollectionOf{0}")]

public class MyCollection<T>: IEnumerable<T>

    {

public void Add(T item)

        { }

public IEnumerator<T> GetEnumerator()

        {

throw new NotImplementedException();

        }

    }

}

服务契约修改为:

namespace ContractInterface

{

    [ServiceContract]

public interface IContractManager

    {

        [ OperationContract]

List<Contract> GetContracts();

[OperationContract ]

MyCollection<Contract> GetContract();

    }

}

则,导出的客户端定义为:

MyCollectionOfContract GetContract();

集合类重新编组为

public class MyCollectionOfContract : System.Collections.Generic.List<Contract > {

    }

     在装载服务时,特性会检查Add方法和IEnumerable或者IEnumerable<T>是否存在,如果不存在而引发InvalidDataContractException异常。

     注意,不能同时将DataContract和CollecctionDataContract应用到集合类型上,在装载服务的时候同样会检查这一点。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java一日一条

Java 函数调用是传值还是传引用?从字节码角度来看看 !

https://www.oschina.net/question/2507499_2244027,其中的变量a前后的输出是什么?

683
来自专栏偏前端工程师的驿站

意译:《JVM Internals》

译者语                                  为加深对JVM的了解和日后查阅时更方便,于是对原文进行翻译。内容是建立在我对JVM的认...

1967
来自专栏java一日一条

java内存分配和String类型的深度解析

在java语言的所有数据类型中,String类型是比较特殊的一种类型,同时也是面试的时候经常被问到的一个知识点,本文结合java内存分配深度分析关于String...

341
来自专栏葡萄城控件技术团队

最全数据结构详述: List VS IEnumerable VS IQueryable VS ICollection VS IDictionary

本文对常用的数据结构详述:Array, ArrayList,List,IList,ICollection, Stack, Queue, HashTable, D...

2088
来自专栏技术博客

编写高质量代码改善C#程序的157个建议[4-9]

  本文首先亦同步到http://www.cnblogs.com/aehyok/p/3624579.html。本文主要来学习记录一下内容:

905
来自专栏程序员互动联盟

【编程基础】C函数的调用过程

这几天在看GCC Inline Assembly,在C代码中通过asm或__asm__嵌入一些汇编代码,如进行系统调用,使用寄存器以提高性能能,需要对函数调用过...

3065
来自专栏MasiMaro 的技术博文

OLEDB 调用存储过程

除了常规调用sql语句和进行简单的插入删除操作外,OLEDB还提供了调用存储过程的功能,存储过程就好像是用SQL语句写成的一个函数,可以有参数,有返回值。 ...

501
来自专栏Ryan Miao

java基础面试题

参考:http://blog.csdn.net/jackfrued/article/details/44921941 说未经允许不转载,我只好参考了。 1.面向...

3085
来自专栏程序员互动联盟

【C++练手】C++实现单链表

前几天找实习的时候,一个面试官给我留了一个题,做一个链表demo,要求实现创建、插入、删除等操作。 链表是一种常见的数据结构,它是一种物理存储单元上非连续、非顺...

3267
来自专栏linux驱动个人学习

Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析【转】

Android系统的运行时库层代码是用C++来编写的,用C++ 来写代码最容易出错的地方就是指针了,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃。不过系统为...

522

扫描关注云+社区