WCF初探-17:WCF数据协定之等效性
数据协定等效性特点概述
- 对于客户端要将某种类型的数据成功发送到服务,或者服务要将数据成功发送到客户端的情况,接收端上并不一定必须存在此发送数据类型。 唯一的要求是两种类型的数据协定应该等效。
- 要使数据协定等效,其命名空间和名称必须相同。 此外,某一端上的每个数据成员还必须在另一端上具有等效的数据成员。注意,数据协定名称和命名空间以及数据成员名称均区分大小写。
- 要使数据成员等效,其名称必须相同。 此外,它们还必须表示同一类型的数据,也就是说,其数据协定必须等效。
- 如果同一端(发送方或接收方)存在两种类型,而其数据协定又不等效(例如,它们的数据成员不同),则不应为它们指定相同的名称和命名空间。 否则,可能会引发异常。
- 使用 DataMemberAttribute 类的 Order 属性可能会影响数据协定等效性。 其成员必须以相同顺序出现,数据协定才能等效。
数据协定等效性说明
- 在上图中,我们在服务端定义了数据协定为User和Person的类,他们在客户端都会生成和标记3一样的客户端数据契约类型。因此,我们称User和Person是具有等效性的数据契约。
- 数据协定的等效性要求只与上面的数据协定等效性特点概述有关,与数据协定本身的类定义无关。也就是说,只要在服务端定义的数据契约类型在客户端代理类中生成相同的数据契约,我们就称服务端的这些数据协定具有等效性。
- 有了上述特点,我们就可以在服务端任意替换具有等效性的数据协定,而不必修改和重新生成客户端,客户端都能正常运行
数据协定等效性示例
- 解决方案如下:
- 工程结构说明
- Service:类库类型,WCF服务端程序。IUserInfo.cs代码如下:
using System.ServiceModel;
using System.Runtime.Serialization; namespace Service
{
[ServiceContract]
public interface IUserInfo
{
[OperationContract]
User[] GetInfo();
} [DataContract]
public class User
{
[DataMember]
public int ID { get; set; } [DataMember]
public string Name { get; set; } [DataMember]
public int Age { get; set; } [DataMember]
public string Nationality { get; set; }
}
}
UserInfo.cs代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace Service
{
public class UserInfo:IUserInfo
{
public User[] GetInfo()
{
List<User> Users = new List<User>();
Users.Add(new User { ID = , Name = "JACK", Age = , Nationality = "CHINA" });
Users.Add(new User { ID = , Name = "TOM", Age = , Nationality = "JAPAN" });
Users.Add(new User { ID = , Name = "SMITH", Age = , Nationality = "KOREA" });
Users.Add(new User { ID = , Name = "ALENCE", Age = , Nationality = "INDIA" });
Users.Add(new User { ID = , Name = "JOHN", Age = , Nationality = "SINGAPORE" }); return Users.ToArray();
}
}
}
2. Host:控制台应用程序,WCF服务承载程序。添加对Service程序集的引用,完成以下代码和配置后就可以寄宿服务。Program.cs的代码如下:
using System;
using System.ServiceModel;
using Service; namespace Host
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(UserInfo)))
{
host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
host.Open();
Console.Read();
}
}
}
}
App.config的代码如下:
<?xml version="1.0"?>
<configuration>
<system.serviceModel> <services>
<service name="Service.UserInfo" behaviorConfiguration="mexBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:1234/UserInfo/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="Service.IUserInfo" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services> <behaviors>
<serviceBehaviors>
<behavior name="mexBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
我们通过svcutil.exe工具生成客户端代理类和客户端的配置文件
svcutil.exe是一个命令行工具,位于路径C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin下,我们可以通过命令行运行该工具生成客户端代理类
- 在运行中输入cmd打开命令行,输入 cd C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin
- 输入svcutil.exe /out:f:\UserInfoClient.cs /config:f:\App.config http://localhost:1234/UserInfo
3. Client:控制台应用程序,客户端调用程序。将生成的UserInfoClient.cs和App.config复制到Client的工程目录下,完成客户端调用代码。Program.cs的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Service; namespace Client
{
class Program
{
static void Main(string[] args)
{
UserInfoClient proxy = new UserInfoClient();
User[] Users = proxy.GetInfo();
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality");
for (int i = ; i < Users.Length; i++)
{
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
Users[i].ID.ToString(),
Users[i].Name.ToString(),
Users[i].Age.ToString(),
Users[i].Nationality.ToString());
} Console.Read();
}
}
}
4. 程序运行效果如下:
数据协定等效性验证
- 接下来,我们修改服务端的数据协定,并且修改操作协定的实现代码。IUserInfo.cs的代码如下:
using System.ServiceModel;
using System.Runtime.Serialization; namespace Service
{
[ServiceContract]
public interface IUserInfo
{
[OperationContract]
Person[] GetInfo();
} [DataContract(Name = "User")]
public class Person
{
[DataMember]
public int ID { get; set; } [DataMember(Name = "Name")]
public string 姓名 { get; set; } [DataMember]
public int Age { get; set; } [DataMember]
public string Nationality { get; set; }
}
}
UserInfo.cs的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace Service
{
public class UserInfo:IUserInfo
{
public Person[] GetInfo()
{
List<Person> Persons = new List<Person>();
Persons.Add(new Person { ID = , 姓名 = "JACK", Age = , Nationality = "CHINA" });
Persons.Add(new Person { ID = , 姓名 = "TOM", Age = , Nationality = "JAPAN" });
Persons.Add(new Person { ID = , 姓名 = "SMITH", Age = , Nationality = "KOREA" });
Persons.Add(new Person { ID = , 姓名 = "ALENCE", Age = , Nationality = "INDIA" });
Persons.Add(new Person { ID = , 姓名 = "JOHN", Age = , Nationality = "SINGAPORE" }); return Persons.ToArray();
}
}
}
- 修改后我们保存并重新生成Host程序,Client程序不做任何操作。运行结果和先前一样,说明两次定义的数据协定时等效的。程序运行效果如下:
- 接下来,我们再次修改数据协定,为数据协定的成员添加Order属性,修改代码如下所示,修改后我们重新编译Host,运行程序。运行后我们发现程序没有报错。但是ID和Age的值都变成了0,说明契约的等效性受Order的影响。
[DataContract(Name = "User")]
public class Person
{
[DataMember(Order = )]
public int ID { get; set; } [DataMember(Name = "Name")]
public string 姓名 { get; set; } [DataMember(Order = )]
public int Age { get; set; } [DataMember(Order = )]
public string Nationality { get; set; }
}
WCF初探-17:WCF数据协定之等效性的更多相关文章
- WCF技术剖析之十六:数据契约的等效性和版本控制
原文:WCF技术剖析之十六:数据契约的等效性和版本控制 数据契约是对用于交换的数据结构的描述,是数据序列化和反序列化的依据.在一个WCF应用中,客户端和服务端必须通过等效的数据契约方能进行有效的数据交 ...
- 我们一起学习WCF 第五篇数据协定和消息协定
A:数据协定(“数据协定”是在服务与客户端之间达成的正式协议,用于以抽象方式描述要交换的数据. 也就是说,为了进行通信,客户端和服务不必共享相同的类型,而只需共享相同的数据协定. 数据协定为每个参数或 ...
- WCF学习心得------(六)数据协定
--前言 最近各种事忙的把之前的WCF学习给耽误了一些,今天抽时间把之前的学习内容给总结了一下,因为知识点比较细碎没有做太多的练习示例,只是对其中关键的知识点做了总结,希望可以对大家有所帮助. 第六章 ...
- WCF基础之数据协定
数据协定最重要的当然就是DataContract和DataMember.这两个特性能应用到类.结构和枚举.这个两个特性跟服务契约的特点是一样的,只有被DataContract标记的类和类中被标记Dat ...
- WCF初探文章列表
WCF初探-1:认识WCF WCF初探-6:WCF服务配置 WCF初探-2:手动实现WCF程序 WCF初探-7:WCF服务配置工具使用 WCF初探-3:WCF消息交换模式之单向模式 WCF初探-8:W ...
- WCF初探-16:WCF数据协定之基础知识
数据协定概念 “数据协定”是在服务与客户端之间达成的正式协议,用于以抽象方式描述要交换的数据. 也就是说,为了进行通信,客户端和服务不必共享相同的类型,而只需共享相同的数据协定. 数据协定为每一个做数 ...
- WCF初探-18:WCF数据协定之KnownType
KnownTypeAttribute 类概述 在数据到达接收终结点时,WCF 运行库尝试将数据反序列化为公共语言运行库 (CLR) 类型的实例.通过首先检查传入消息选择为反序列化而实例化的类型,以确定 ...
- WCF初探-14:WCF服务协定
前言: 在前面的文章中,我们定义的服务协定上都会有一个ServiceContract的特性来修饰,这是因为服务契约的实现要靠ServiceContractAttribute 属性定义,然后使用一个或多 ...
- WCF初探-20:WCF错误协定
WCF错误协定概述 在所有托管应用程序中,处理错误由 Exception 对象表示. 在基于 SOAP 的应用程序(如 WCF 应用程序)中,服务方法使用 SOAP 错误消息来传递处理错误信息. SO ...
随机推荐
- Life is hard
Life is hard, always so.If there's anything to give you a hard life with sunshine and warmth, please ...
- url.py中的配置问题
urlpatterns = [ url(r'^add$', calc_views.add, name='add'), url(r'^admin/', admin.site.urls), ...
- 列间距column-gap
column-gap主要用来设置列与列之间的间距,其语法规则如下: column-gap: normal || <length> 取值说明 属性值 属性值说明 normal 默认值,默值为 ...
- 关注微信 即可连上wifi 的设计思路
这个功能之前是在知乎上有人在询问后台的实现逻辑,然后才知道的。其实对微信的各种关注,实在是不想沾惹。 但是这个功能很有意思,当我关注了你,那么就可以在你的店里上wifi 。如果取消则立刻不能上网。 这 ...
- window.event对象详尽解析
event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等. event对象只在事件发生的过程中才有效. event的某些属性只对特定的事件有意义.比如,fromEleme ...
- Mac 使用笔记
说来惭愧,入手Mac已经快大半年了,但使用上一直是菜鸟. 下面是最近学习和用到的技巧,纪录如下,以后会不定期更新. 开启多个Terminal,这个简直是调程序必备. Command+N 打开新的Ter ...
- An internal error occurred during: "Building workspace".
当在eclipse中的web工程中增加了extjs4,出现An internal error occurred during: "Building workspace". Java ...
- Linux命令学习整理。
http://www.cnblogs.com/suliuer/p/5448747.html 本文主要包括两部分,一是Linux基础命令的总结:二是总结一些常用的命令知识点. 一.基础总结 学习Linu ...
- Web Performance Test : IP切换/IP欺骗
译者前言 本文翻译自<Visual Studio Performance Testing Quick Reference Guide 3.6> 有关于IP Switching的章节.< ...
- Excel公式错误提示啥意思?
1.#####!返回的结果超出了单元格的宽度:或者单元格的日期时间公式产生了一个负值. 2.#VALUE!使用了错误的参数或运算对象类型. 3.#DIV/O!当公式被零除时产生此错误. 4.#NAME ...