技術准備:
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來設置非數據成員的值。
首先我們來定義一個數據契約:
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方法中設計了其值。
下面是服務契約:
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);
}
}
服務契約的實現:
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
}
}
宿主主機的代碼比較簡單就是暴露了一個終節點給客戶端。
我們看下客戶端的代碼:
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();
}
}
}
運行主機跟客戶端後我們看到了想要的效果: