一、数据协定基本知识
默认情况下,Windows Communication Foundation (WCF) 使用称为 数据协定序列化程序的序列化引擎对数据进行序列化和反序列化(与 XML 进行相互转换)。
必须为所创建的新复杂类型,定义数据协定以便可以进行序列化。 正常情况下可通过将 属性应用到该类型来完成该任务。 可以将此属性应用到类、结构和枚举。 然后必须将 属性应用到数据协定类型的每个成员,以指示这些成员为数据成员, 即应进行序列化
看个例子:
![](https://i-blog.csdnimg.cn/blog_migrate/1b11fc60b43f911d6ed92679d23c3f23.png)
上面的示例演示,如何通过将 DataContractAttribute 和 DataMemberAttribute 属性应用于类及其成员来创建
MyTypes.PurchaseOrder
类型的数据协定。
需要注意的:
a.数据协定是使用“选择性加入”编程模型设计的;未用 DataMemberAttribute 属性显式标记的任何内容均不序列化。(个人认为是Data Contract与外界数据的一种协议)
b.可以将 DataMemberAttribute 属性应用于字段、属性和事件。
c.成员可访问性级别(internal、private、protected 或 public)对数据协定无任何影响。(相互独立)
d.如果将 DataMemberAttribute 属性应用于静态成员,则将忽略该属性。
e.在序列化期间,为属性数据成员调用 property-get 代码来获取要序列化的属性的值。(GET索引器起到获取值的作用)
f.在反序列化期间,首先创建一个未初始化的对象,而不在该类型上调用任何构造函数。 然后反序列化所有数据成员。
g.在反序列化期间,为属性数据成员调用 property-set 代码,将属性设置为要反序列化的值。
h.对于将要生效的数据协定,它必须能序列化其所有数据成员。
i.泛型类型的处理方式与非泛型类型完全相同。 (这一点做的真不错)
写的很零碎,可能会有一种云里雾里的感觉.下面,我会写出一段真实的case.这个case将使您会得到一个正在运行的服务,以及一个可以调用该服务操作的客户端.
本例jason准备用两部分主题来完成:
1.编写server程序
1.1:如何使用协定,定义服务?
1.2:如何实现服务?
1.3:如何在代码中配置服务、承载服务和运行服务
2.编写client程序
2.1:如何创建客户端代理?
2.2:如何配置客户端应用程序?
2.3:如何创建和使用可以访问服务功能的客户端
带着这些问题,我们继续......
在软件工程领域,我们设计软件的架构,到目前为止,主流的还是C/S、B/S。早期的开发模式,c/s占据主导地位.那么,我就以此模式入手.
创建基本 WCF 服务时,第一项任务就是,创建与外界共享的服务协定,并在其中描述如何与该服务进行通信。 此协定指定访问服务所提供的操作,以及必需的消息的集合和结构.我们可以通过创建定义输入和输出类型的接口来执行此操作.
那么,如何通过接口来创建WCF的契约呢?(注:Contract的叫法不同,本文仅称为:契约)
请看例子:
创建接口之后,下一步就是实现接口.我们知道,接口是把隐式的公共方法和属性组合起来,以封装 特定功能的一个集合。一旦实现了接口,类就可以支持接口所指定的所有属性和成员.ok.那就上我们看看,如何用类来实现WCF服务契约!
using System;
using System.ServiceModel;
namespace Microsoft.ServiceModel.Samples
{
// 定义服务契约.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
}
// Step 1: 定义一个类,来实现服务契约接口ICalculator.
public class CalculatorService : ICalculator
{
// Step 2: 实现服务功能
public double Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
// 添加数据到应用程序控制台输出
Console.WriteLine("Return: {0}", result);
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
}
}
创建和实现了服务协定后,创建 WCF 服务的下一步是运行该服务。运行服务由三个步骤组成:配置、承载和打开服务。
哈哈.终于到了最激动人心的时刻!
运行基本的WCF 服务。这个过程应包含以下步骤:
Step1.为服务创建基址。
Step2.为服务创建服务主机。
Step3.启用元数据交换。
Step4.打开服务主机
代码如下:
class Program
{
static void Main(string[] args)
{
// Step 1 为服务的基址创建 Uri 实例。 此 URI 指定 HTTP 方案、本地计算机、端口号 8000,以及服务协定中为服务命名空间指定的服务路径
Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");
// Step 1 创建一个新的 ServiceHost 实例以承载服务。必须指定实现服务协定和基址的类型.
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);
try
{
// Step 3 添加公开服务的终结点。 为此,必须指定终结点公开的协议、绑定和终结点的地址.
selfHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService");
// Step 4 启用元数据交换.为此,必须添加服务元数据行为。 首先创建一个 ServiceMetadataBehavior 实例,将 HttpGetEnabled 属性设置为 true,然后为服务添加新行为.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Step 5 打开 ServiceHost 并等待传入消息.按 Enter 键时,关闭 ServiceHost。
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// 停止the ServiceHostBase服务
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
}
}
}