WCF学习(三)-------数据契约1

本文详细介绍了 WCF 中的数据契约特性及其使用方法,包括 DataContract 和 DataMember 的应用,以及如何自定义序列化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    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#region Fileds

        
private string _firstName;
        
private string _lastName;
        
private int _age;
        
private decimal _salary;

        
#endregion

        
        
Attributes#region Attributes
       
        [DataMember(Name
="FirstName",IsRequired=false,Order=0)]
        
public string FirstName
        
{
            
get return this._firstName; }
            
set this._firstName = value; }
        }


        [DataMember(Name 
= "LastName", IsRequired = false, Order = 1)]
        
public string LastName
        
{
            
get return this._lastName; }
            
set this._lastName = value; }
        }


        [DataMember(Name 
= "Age", IsRequired = false, Order = 2)]
        
public int Age
        
{
            
get return this._age; }
            
set this._age = value; }
        }


        [DataMember(Name 
= "Salary", IsRequired = false, Order = 3)]
        
public decimal Salary
        
{
            
get return this._salary; }
            
set this._salary = value; }
        }


        
#endregion

    }

}

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

服务契约为:
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.ServiceModel;

namespace  HenllyeeServiceContract
{
    [ServiceContract(Name
="CustomerManagerService",Namespace="http://Henllyee.cnblogs.com/2008/06/29")]
    
public interface ICustomerManager
    
{
        
/**//// <summary>
        
/// Save customer's info
        
/// </summary>
        
/// <param name="customer">the customer's object</param>

        [OperationContract(Name="SaveCustomerInfo",Action="http://Henllyee.cnblogs.com/2008/06/29/CustomerManagerService/SaveCustomer",
            ReplyAction 
= "http://Henllyee.cnblogs.com/2008/06/29/CustomerManagerService/SaveCustomerResponse")]
        
void SaveCustomer(HenllyeeDataContract.Customer customer);

        
/**//// <summary>
        
/// Get customer's info
        
/// </summary>
        
/// <returns>a customer</returns>

        [OperationContract(Name = "GetCustomerInfo", Action = "http://Henllyee.cnblogs.com/2008/06/29/CustomerManagerService/GetCustomer",
            ReplyAction 
= "http://Henllyee.cnblogs.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#region fileds

        
private HenllyeeDataContract.Customer _customer;

        
#endregion


        
Members#region Members 
        
        
public void SaveCustomer(HenllyeeDataContract.Customer customer)
        
{
            _customer 
= customer;
            
        }


        
public HenllyeeDataContract.Customer GetCustomer()
        
{
            
return this._customer;
        }

        
#endregion

    }

}



主机的实现就不在次给出了。
然后我们在客户端添加服务引用,即可以了。我们在客户端可以看到导入的数据契约:
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute(
" System.Runtime.Serialization " " 3.0.0.0 " )]
    [System.Runtime.Serialization.DataContractAttribute(Name
= " Customer " , Namespace = " HenllyeeDataContract " )]
    [System.SerializableAttribute()]
    
public   partial   class  Customer :  object , System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged  {
        
        [System.NonSerializedAttribute()]
        
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
        
        [System.Runtime.Serialization.OptionalFieldAttribute()]
        
private string FirstNameField;
        
        [System.Runtime.Serialization.OptionalFieldAttribute()]
        
private string LastNameField;
        
        [System.Runtime.Serialization.OptionalFieldAttribute()]
        
private int AgeField;
        
        [System.Runtime.Serialization.OptionalFieldAttribute()]
        
private decimal SalaryField;
        
        [
global::System.ComponentModel.BrowsableAttribute(false)]
        
public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
            
get {
                
return this.extensionDataField;
            }

            
set {
                
this.extensionDataField = value;
            }

        }

        
        [System.Runtime.Serialization.DataMemberAttribute()]
        
public string FirstName {
            
get {
                
return this.FirstNameField;
            }

            
set {
                
if ((object.ReferenceEquals(this.FirstNameField, value) != true)) {
                    
this.FirstNameField = value;
                    
this.RaisePropertyChanged("FirstName");
                }

            }

        }

        
        [System.Runtime.Serialization.DataMemberAttribute()]
        
public string LastName {
            
get {
                
return this.LastNameField;
            }

            
set {
                
if ((object.ReferenceEquals(this.LastNameField, value) != true)) {
                    
this.LastNameField = value;
                    
this.RaisePropertyChanged("LastName");
                }

            }

        }

        
        [System.Runtime.Serialization.DataMemberAttribute(Order
=2)]
        
public int Age {
            
get {
                
return this.AgeField;
            }

            
set {
                
if ((this.AgeField.Equals(value) != true)) {
                    
this.AgeField = value;
                    
this.RaisePropertyChanged("Age");
                }

            }

        }

        
        [System.Runtime.Serialization.DataMemberAttribute(Order
=3)]
        
public decimal Salary {
            
get {
                
return this.SalaryField;
            }

            
set {
                
if ((this.SalaryField.Equals(value) != true)) {
                    
this.SalaryField = value;
                    
this.RaisePropertyChanged("Salary");
                }

            }

        }

        
        
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        
        
protected void RaisePropertyChanged(string propertyName) {
            System.ComponentModel.PropertyChangedEventHandler propertyChanged 
= this.PropertyChanged;
            
if ((propertyChanged != null)) {
                propertyChanged(
thisnew System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }

        }

    }

我们可以看到字段后面都加上了Field后缀。
要注意的一点是:即使我们将DataMember定义在私有的字段或者私有属性上面,导入的定义中,原来的私有字段或私有属性都会被重新定义成了公有字段跟公有属性。
文件下载地址: http://files.cnblogs.com/henllyee/DataContract.rar

转载于:https://www.cnblogs.com/Henllyee/archive/2008/07/03/1234584.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值