技术准备:
1.dotnet基本开发;
2.WCF的数据契约跟服务契约的基本使用
内容:
我们都知道数据契约其实也是服务器端到客户端序列化跟反序列化,这样的序列化跟asp.net ajax访问webservice是很像的.asp.net ajax 一般是将服务器端的数据序列化成jason字符串传递给前台脚本的但是我们在序列化或则反序列化的时候也许会要去控制一些数据契约里面的Filed或则Attributes,这就需要我们去监听数据契约在序列化及反序列化时触发的一些事件。
数据契约的事件
数据契约在序列化跟反序列化分别有四个事件:
1.serializing事件:发生在序列化之前;
2.serialized事件:发生在序列化之后;
3.deserializing事件:反序列化之前;
4.deserialized事件:反序列化之后;
四个事件我们一眼就能看得懂。但是我们如何去监听这几个事件呢,WCF提供了四个属性标识来标识我们定义的某个方法是来监听标识的特定的事件。但是我们在定义方法的时候必须要去符合这些事件的委托的类型,也就是说必须有相同的参数。我们看下定义的形式:
1.监听serializing事件:
[OnSerializing]
void OnSerializing(StreamingContext context)
2.监听serialized事件:
[OnSerialized]
void OnSerialized(StreamingContext context)
3.监听deserializing事件:
[OnDeserializing]
void OnDeserializing(StreamingContext context)
4.监听deserialized事件:
[OnDeserialized]
void OnDeserialized(StreamingContext context)
所以我们可以看出我们定义的方法一定要符合 void <methdName>(StringmingContext <Pram>)的形式,不然WCF就会抛出异常。要注意的一点就是:我们不能把相同的事件的标识应用到多个方法上面。
因为在反序列化的时候是没有构造函数被调用的,所以我们可以通过OnDeserializing来实现反序列化的构造函数的功能。OnDeserialized事件允许初始化数据契约或则非数据契约的成员。下面我们就看一个例子通过监听OnDeserialized来设置非数据成员的值。
首先我们来定义一个数据契约:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace DataContract
{
[DataContract(Name="Employee",Namespace="HenllyeeData")]
public class EmployeeEntry
{
#region Fields
private string _companyName;
private string _name;
private int _age;
private decimal _salary;
#endregion
#region Attributes
[DataMember(IsRequired=false,Order=0)]
public string Name
{
get { return this._name; }
set { this._name = value; }
}
[DataMember(IsRequired=false,Order=1)]
public int Age
{
get { return this._age; }
set { this._age = value; }
}
[DataMember(IsRequired=false,Order=2)]
public decimal Salary
{
get { return this._salary; }
set { this._salary = value; }
}
[DataMember(IsRequired=false,Order=3)]
public string Info
{
get
{
return String.Format("Name:{0} \n Age:{1} \n; Salary:{2}\n CompanyName:{3}\n",
this._name,
this._age,
this._salary,
this._companyName);
}
set
{
}
}
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
this._companyName = "ECI";
}
#endregion
}
}
在这里面我们定义了一个_companyName字段,并且不表示为DataMember,但是在Info属性中去获取了_companyName的值。我们在反序列化的时候完后通过OnDeserizlized方法中设计了其值。
下面是服务契约:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace ServiceContract
{
[ServiceContract(Name="EmployeeManagerService")]
public interface IEmployeeManager
{
/// <summary>
/// Get a employee object
/// </summary>
/// <returns></returns>
[OperationContract(Name="GetEmployee")]
DataContract.EmployeeEntry GetEmployee();
/// <summary>
/// Save a employee object
/// </summary>
/// <param name="?"></param>
[OperationContract(Name="SaveEmployee")]
void SaveEmplyee(DataContract.EmployeeEntry employee);
}
}
服务契约的实现:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace ServiceContract
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class EmployeeManager:IEmployeeManager
{
#region Fields
private DataContract.EmployeeEntry _employee;
#endregion
#region Methods
public DataContract.EmployeeEntry GetEmployee()
{
return this._employee;
}
public void SaveEmplyee(DataContract.EmployeeEntry EmloyeeEntry)
{
this._employee = EmloyeeEntry;
}
#endregion
}
}
宿主主机的代码比较简单就是暴露了一个终节点给客户端。
我们看下客户端的代码:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
EmployeeServiceReference.Employee emloyee = new ConsoleApplication1.EmployeeServiceReference.Employee();
emloyee.Name = "Henllyee";
emloyee.Age = 22;
emloyee.Salary = 3000;
EmployeeServiceReference.EmployeeManagerServiceClient proxy = new ConsoleApplication1.EmployeeServiceReference.EmployeeManagerServiceClient();
proxy.SaveEmployee(emloyee);
EmployeeServiceReference.Employee emploOut= proxy.GetEmployee();
Console.Write(emploOut.Info);
Console.Read();
}
}
}
运行主机跟客户端后我们看到了想要的效果:
[代码下载]