准备技术:

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace HenllyeeDataContract
{
    [DataContract]
    public class Employee
    {
        #region Fields
        private string _name;
        private int _age;
        #endregion

#region Properties
        /// <summary>
        /// The employee's name
        /// </summary>
        [DataMember(Order=0)]
        public string Name
        {
            get 
            {
                return this._name;
            }
            set
            {
                this._name = value;
            }
        }

/// <summary>
        /// The employee's age
        /// </summary>
        [DataMember(Order=1)]
        public int Age
        {
            get
            {
                return this._age;
            }
            set
            {
                this._age = value;
            }
        }
        #endregion
    }

[DataContract]
    public class Intern : Employee
    {
        private int _internship;

/// <summary>
        /// The intern's working days
        /// </summary>
        [DataMember]
        public int Internship
        {
            get
            {
                return this._internship;
            }
            set
            {
                this._internship = value;
            }
        }
    }
}

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

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace HenllyeeServiceContract
{
    [ServiceContract]
    public interface IEmployeeManage
    {
        [OperationContract]
        [ServiceKnownType(typeof(HenllyeeDataContract.Intern))]
        void AddEmployee(HenllyeeDataContract.Employee emlpoyee);

[OperationContract]
        [ServiceKnownType(typeof(HenllyeeDataContract.Intern))]
        HenllyeeDataContract.Employee GetEmployee();
    }

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class EmployeeManage : IEmployeeManage
    {
        private HenllyeeDataContract.Employee _employee;

/// <summary>
        /// Set employee
        /// </summary>
        /// <param name="emlpoyee">the employee's object</param>
        public void AddEmployee(HenllyeeDataContract.Employee emlpoyee)
        {
            this._employee = emlpoyee;
        }

/// <summary>
        /// Get a employee
        /// </summary>
        /// <returns></returns>
        public HenllyeeDataContract.Employee GetEmployee()
        {
            return this._employee;
        }
    }
}

在客户端我们调用:

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            EmployeeService.EmployeeManageClient proxy = new Client.EmployeeService.EmployeeManageClient();
            EmployeeService.Intern intern = new Client.EmployeeService.Intern();
            intern.Age = 22;
            intern.Name = "Henllyee Cui";
            intern.Internship = 120;
            proxy.AddEmployee(intern);

EmployeeService.Employee internOut = proxy.GetEmployee();
            Console.Write("The Employee Name:{0}\nAge:{1}\n",
                internOut.Name,
                internOut.Age
                );
            Console.Read();
        }
    }
}

运行后:

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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。

转载于:https://www.cnblogs.com/Henllyee/archive/2008/08/26/1276995.html

WCF学习(五)数据契约之已知类型相关推荐

  1. WCF步步为营(五):数据契约

    . WCF只能传输序列化的类型,WCF 能自动序列化.net内置的之类型,但是如果需要传输自定义的类型,必须把自定义的类型标注DataContract DataContract标注这个类作为数据契约, ...

  2. 已知某个班有 30 个学生,学习 5 门课程,已知所有学生的各科成绩。计算每个学生的平均成绩,并输出

    已知某个班有 30 个学生,学习 5 门课程,已知所有学生的各科成绩.计算每个学生的平均成绩,并输出 注意: 定义一个二维数组 A,用于存放 30 个学生的 5 门成绩. 定义一个一维数组 B,用 于 ...

  3. WCF学习(二):契约

    (原创:灰灰虫的家http://hi.baidu.com/grayworm) 契约是WCF中很重要的概念.它是用一种与平台无关的标准语法来描述WCF服务的功能.当客户端获取服务端WCF服务的时候,会根 ...

  4. Python 一个判断对象是否是一个已知类型的函数-isinstance()

    描述 isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type(). isinstance() 与 type() 区别: type() 不会认为子类是一种父类类型,不考虑继承关 ...

  5. (2) 第二章 WCF服务与数据契约 服务契约详解(三)- [ServiceContract]特性

    本章节主要目的:了解[ServiceContract]特性 如前几章的进度,相信已经可以自己编写服务契约以及如何在客户端调用配置好的服务了. 本片主要讲解一下SerivceContract中的几个重要 ...

  6. (2) 第二章 WCF服务与数据契约 服务契约详解(二)- 如何引用WCF提供的服务

    本章节主要目的:掌握如何引用WCF提供的服务 下面来讲解一下如何引用WCF的服务,主要讲解2种方式: 1.Service References 操作步骤:1.在项目中右键鼠标->2.点击添加引用 ...

  7. swift学习五天 项目实战-知乎日报之网络交互NSURLConnection

    这里附上代码下载地址:     http://download.csdn.net/detail/guchengyunfeng/7989139 网络接口 格式: 协议1: http://news-at. ...

  8. Python学习之学校教学( 已知复数,请写出它的模、实部、虚部及共轭复数)

    我们把形如z=a+bi(a,b均为实数)的数称为复数,其中a称为实部,b称为虚部,i称为虚数单位.当z的虚部等于零时,常称z为实数:当z的虚部不等于零时,实部等于零时,常称z为纯虚数.复数域是实数域的 ...

  9. 03 数据契约_03 数据契约层级(DataContract Hierarchy)

    数据契约层级(DataContract Hierarchy) 已知类型 大多数情况下,WCF不能使用数据契约的子类去替换基类 解决上述问题--KnownTypeAttribute 服务已知类型 弥补K ...

最新文章

  1. socket connect阻塞和非阻塞处理
  2. c语言实现定长顺序存储,c语言:定长顺序串的基本操作实实现
  3. Linux新建用户图解
  4. Python实例 -- 如何快速获取列表中最大的三个元素
  5. 使用SSMS操作数据-sql
  6. 深入理解javascript原型和闭包(3)——prototype原型
  7. mysql外键设置sql语句,SQL Server 2008之SQL语句外键
  8. 含有任意量词与存在量词的最值问题
  9. BASE64Encoder及BASE64Decoder的正确用法
  10. 在教学中利用计算机软件,计算机软件技术教学方法研究
  11. windows下Eclipse调试ffmpeg
  12. 趣头条将获得阿里1.71亿美元的可转债,为期三年
  13. sudo: must be setuid root错误解决方法.
  14. 三、Oracle学习笔记:DDL数据定义语句
  15. 科学家发现程序员秃头新原因,毛囊干细胞竟会悄悄逃走
  16. QuickCHM 2.6“不支持此接口”错误的解决
  17. 【saltstack】认证失败,无法生成minion_master.pub问题处理总结
  18. Guava 之 Splitter
  19. python计算余弦相似度
  20. javase加强,十、IO流2

热门文章

  1. python随机生成数字列表_详解Python利用random生成一个列表内的随机数
  2. brainfu*k语言执行
  3. Python函数参数传递:传值还是传引用
  4. 分布式Matlab计算集群建立方法与Demo
  5. AUTOSAR从入门到精通100讲(三十九)-AUTOSAR 通信服务-Com模块两部曲-概念详解
  6. 全量增长模型-指标体系的构建及应用实战案例解析
  7. Python办公自动化,对文件进行自由操作
  8. mysql5.7环境,MySQL-5.7-线上生产环境部署
  9. php 避免xss_PHP防止XSS注入
  10. 5.1.2全景声音箱摆位_如何体验全景声