WCF學習(四):資料契約的事件

iDotNetSpace發表於2009-05-18

技術準備:

     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 (StringmingContext )的形式,不然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
    {
        ///


        /// Get a employee object
        ///

        ///
        [OperationContract(Name="GetEmployee")]
        DataContract.EmployeeEntry GetEmployee();
       
        ///
        /// Save a employee object
        ///

        ///
        [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();
           
        }
    }
}

 

 執行主機跟客戶端後我們看到了想要的效果:

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-600251/,如需轉載,請註明出處,否則將追究法律責任。

相關文章