代码改变世界

WCF学习(五)数据契约之已知类型

2008-08-26 20:19  Henry Cui  阅读(1888)  评论(3编辑  收藏  举报

准备技术:

     1.C#基础知识

     2.了解WCF基础知识

 

 

     在正常的c#开发中我们是允许用子类去替换基类的,这也是所谓的替换原则。但是我们在WCF中确不能用数据契约的子类来替换父类的,因为这中间存在一个序列化的问题。举个例子:

     我们有数据契约:

          [DataContract]

          class Employee{...}

     服务契约中:

          [ServiceContract]

          interface IEmployeeManager

          {

               [OperationContract]

               void AddEmployee(Employee employee);

          }

     然后我们在客户端的代理中就算有类:Intern继承于

          [DataContract]

          class Intern:Employee{...}

     然后再客户端调用时:

          proxy.AddEmployee(new Intern())是会出错的。因为在服务器端无法识别Intern对象,因为他无法去反序列化Intern成Employee对象(WCF序列化)。

     

     

     WCF提供给我们了一个解决的办法就是使用KnownTypeAttribute特性,在基类上标识对应的子类就可以了。KnownTypeAttribute特性可以使用在Struct跟Class上。示例:

          [DataContract]

          [KnownType(typeof(Customer))]

          class Employee{...}

          

          [DataContract]

          class Intern:Employee{...}

这样我们就在所有的契约跟操作上,能跨越所有的服务和终结点,允许服务接受子类。但是这样会遇到一个问题,我们不能去特定的指定某一个服务操作,所以KnownType的缺陷就是范围过于广泛。WCF提供了另外一个Attribute--ServiceKnownType.

 

ServiceKnownType 特性

     KnownType只能应用在数据契约的基类上,而ServiceKnownType可以在Interface、Method、Class上标识。看一个示例Employee.cs:

 

Code

 

在数据契约中我们并没有去指定KnownType,我们在服务契约的操作上去标识ServiceKnownType特性,EmployeeManage.cs:

 

 

Code

 

在客户端我们调用:

 

 

Code

运行后: 

     ServiceKnownType特性也可以表示在数据契约的类上,那么就会应用到整个数据契约中操作上,如:

          [ServiceContract]

          [ServiceDataContract(typeof(HenllyeeDataContract.Intern))]

          public interface IEmployeeManage{...}

     那么IEmployeeManage服务契约跟其所有的操作都可以接受Intern这个子类.

已知类型与接口

     数据契约DataContract只能标识在class 或者struct上,但是数据契约的基类可以是接口,但是我们在服务契约的时候要去用ServiceKnownType特性去指定确切的数据类型。如:

     interface IEmployee{...}

     [DataContract]

     class Intern:IEmployee{...}

服务契约中:

     [ServiceContract]

     [ServiceKnownType(typeof(Intern))]

     interface IEmployeeManage

     {

          [OperationContract]

          void AdddEmployee(IEmployee employee);

     }

要注意的一点就是我们不能把KnownType特性应用到基接口上,因为客服端导出的元数据是不能包含接口本身的。

[代码下载]

作者:Henllyee Cui
出处: http://henllyee.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。