WCF学习笔记(三),数据契约

 WCF能够托管CLR类型,客户端能传递和处理CLR类型的数据(如:string和int),但是如果我们自己定义的类型(如:声明的Customer类)。其实WCF的传递CLR自己类型时,是因为已经把它序列化成了xml信息集,而我们自己定义的类型则需要自己去显示的声明序列化。

序列化
    .net的序列化。.net是通过反射机制自动实现对象的序列化与反序列化。首先.net能够捕获对象每个字段的值,然后进行序列化,反序列化时,.net创建一个对应类型的新的对象,读取持久化的值,然后设置字段的值。.net对象状态的序列化到Stream中。
    我们自定义的类或者结构是不支持序列化的,因此如果我们的类是否要序列化是需要类的开发者来指定的。如果需要支持序列化的话,我们可以在类或者结构上添加Serializable属性。
    如:
    [Serializable]
    public class Customer
    {
        ...
    }
    但是如果添加了Serializable就要求类型的成员也要支持序列化的,不然会抛出异常,但是我们可以通过在成员上添加NonSerizlized属性来说明这个成员不需要序列化。

格式
    .net为序列化和反序列化提供了两种格式器:
            1.BinaruFormatter:将类型序列化为二进制格式。
            2.SoapFormatter:格式成SOAP特定的XML格式。
    但是这两者都要将类型的程序集以及版本控制信息持久化到Stream中,而面向服务要求参与者都能拥有类型程序集,所以如果用这两种格式就必须要去共享Stream,这样肯定不是我们理想的。从而有了WCF格式器。
    
    WCF的格式器:DataContractSerializer,是能够共享数据契约的。WCF数据进行序列化时,WCF一般会自己调用DataContractSerializer来序列的,不需要我们去指定的。同时我们也可以用DataContractSerializer进行Stream的序列化。

数据契约特性
    Serializable要求类型的所有的成员都是可以序列化的,而且不支持类型名跟成员名的别名,这样我们就没法明确指定哪些成员是要放到数据契约中的。然而WCF数据契约特性DataContract很好的解决了这些问题。
    DataContract Attribute 是在命名空间System.Runtime.Serialization中的,是可以在Enum、Struct、Class上标识的。拥有成员Name,Namespace。而当我们在一个class或者struct上使用时,wcf是不会序列化类型的成员的。如:
        [DataContract]
        public class Emloyee
        {
            public string _firstName;
            public string _lastName;
        }
Employee里面的成员_firstName,_lastName是不会去序列化的,所以我们还必须去显示的指定需要序列化的成员。
    DataMember Attribute是用来指定需要序列化类型的成员。DataMember的成员:
        IsRequried:序列化时是否必须要赋值;
        Name:指定成员的别名;
        Order:指定序列化后的排列位置。
我们看一个例子Customer.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace HenllyeeDataContract
{
    [DataContract(Name
="Customer",Namespace="HenllyeeDataContract")]
    
public class Customer
    
{
        
Fileds
        
        
Attributes
    }

}

 上面我们定义了一个数据契约,将DataMember属性定义在几个属性上(建议定义在属性上,不要定义在字段上)。

服务契约为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace HenllyeeServiceContract
{
    [ServiceContract(Name
="CustomerManagerService",Namespace="www.systhinker.com,专注、技术、共享2008/06/29")]
    
public interface ICustomerManager
    
{
        
/// 
        
/// Save customer's info
        
/// 
        
/// the customer's object

        [OperationContract(Name="SaveCustomerInfo",Action="www.systhinker.com,专注、技术、共享2008/06/29/CustomerManagerService/SaveCustomer",
            ReplyAction 
= "www.systhinker.com,专注、技术、共享2008/06/29/CustomerManagerService/SaveCustomerResponse")]
        
void SaveCustomer(HenllyeeDataContract.Customer customer);

        
/// 
        
/// Get customer's info
        
/// 
        
/// a customer

        [OperationContract(Name = "GetCustomerInfo", Action = "www.systhinker.com,专注、技术、共享2008/06/29/CustomerManagerService/GetCustomer",
            ReplyAction 
= "www.systhinker.com,专注、技术、共享2008/06/29/CustomerManagerService/GetCustomerResponse")]
        HenllyeeDataContract.Customer GetCustomer();
    }

}

服务契约里面具体实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace HenllyeeServiceContract
{
    [ServiceBehavior(InstanceContextMode 
= InstanceContextMode.Single)]
    
public class CustomerManager:ICustomerManager
    
{
        
fileds

        
Members
    }

}



主机的实现就不在次给出了。
然后我们在客户端添加服务引用,即可以了。我们在客户端可以看到导入的数据契约:

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute(
"System.Runtime.Serialization""3.0.0.0")]
    [System.Runtime.Serialization.DataContractAttribute(Name
="Customer", Namespace="HenllyeeDataContract")]
    [System.SerializableAttribute()]
&
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章