WCF Learning(4):WCF中的序列化[下篇]

  XMLSerializer

提到XMLSerializer,我想绝大多数人都知道这是asmx采用的Serializer。首先我们还是来看一个例子,通过比较Managed Type的结构和生成的XML的结构来总结这种序列化方式采用的是怎样的一种Mapping方式。和DataContractSerialzer Sample一样,我们要定义用于序列化对象所属的Type——XMLOrder和XMLProduct,他们和相面对应的DataContractOrder和DataContractProduct具有相同的成员。

using System;
using System.Collections.Generic;
using System.Text;

namespace Artech.WCFSerialization
{
    public class XMLProduct
    {
        Private Fields#region Private Fields
        private Guid _productID;
        private string _productName;
        private string _producingArea;
        private double _unitPrice;
       
        Constructors#region Constructors
        public XMLProduct()
        {
            Console.WriteLine("The constructor of XMLProduct has been invocated!");
        }

        public XMLProduct(Guid id, string name, string producingArea, double price)
        {
            this._productID = id;
            this._productName = name;
            this._producingArea = producingArea;
            this._unitPrice = price;
        }

        #endregion

        Properties#region Properties
        public Guid ProductID
        {
            get { return _productID; }
            set { _productID = value; }
        }

        public string ProductName
        {
            get { return _productName; }
            set { _productName = value; }
        }

        internal string ProducingArea
        {
            get { return _producingArea; }
            set { _producingArea = value; }
        }

        public double UnitPrice
        {
            get { return _unitPrice; }
            set { _unitPrice = value; }
        }

       #endregion

    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace Artech.WCFSerialization
{
    public class XMLOrder
    {
        private Guid _orderID;
        private DateTime _orderDate;
        private XMLProduct _product;
        private int _quantity;

        Constructors#region Constructors
        public XMLOrder()
        {
            this._orderID = new Guid();
            this._orderDate = DateTime.MinValue;
            this._quantity = int.MinValue;

            Console.WriteLine("The constructor of XMLOrder has been invocated!");
        }

        public XMLOrder(Guid id, DateTime date, XMLProduct product, int quantity)
        {
            this._orderID = id;
            this._orderDate = date;
            this._product = product;
            this._quantity = quantity;
        }
        #endregion

        Properties#region Properties
        public Guid OrderID
        {
            get { return _orderID; }
            set { _orderID = value; }
        }

        public DateTime OrderDate
        {
            get { return _orderDate; }
            set { _orderDate = value; }
        }

        public XMLProduct Product
        {
            get { return _product; }
            set { _product = value; }
        }

        public int Quantity
        {
            get { return _quantity; }
            set { _quantity = value; }
        }
        #endregion

        public override string ToString()
        {
            return string.Format("ID: {0}\nDate:{1}\nProduct:\n\tID:{2}\n\tName:{3}\n\tProducing Area:{4}\n\tPrice:{5}\nQuantity:{6}",
                this._orderID,this._orderDate,this._product.ProductID,this._product.ProductName,this._product.ProducingArea,this._product.UnitPrice,this._quantity);
        }
    }
}


编写Serialization的Code.

static void SerializeViaXMLSerializer()
        {
            XMLProduct product = new XMLProduct(Guid.NewGuid(), "Dell PC", "Xiamen FuJian", 4500);
            XMLOrder order = new XMLOrder(Guid.NewGuid(), DateTime.Today, product, 300);
            string fileName = _basePath + "Order.XmlSerializer.xml";
            using (FileStream fs = new FileStream(fileName, FileMode.Create))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(XMLOrder));
                using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs))
                {
                    serializer.Serialize(writer, order);
                }
            }
            Process.Start(fileName);
        }


调用上面定义的方法,生成序列化的XML。

<? xml version="1.0" encoding="utf-8" ?>
< XMLOrder  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd ="http://www.w3.org/2001/XMLSchema" >
    
< OrderID > b695fd18-9cd7-4792-968a-0c0c3a3962c2 </ OrderID >
    
< OrderDate > 2007-03-09T00:00:00+08:00 </ OrderDate >
    
< Product >
        
< ProductID > 23a2fe03-d0a0-4ce5-b213-c7e5196af566 </ ProductID >
        
< ProductName > Dell PC </ ProductName >
        
< UnitPrice > 4500 </ UnitPrice >
    
</ Product >
    
< Quantity > 300 </ Quantity >
</ XMLOrder >

这里我们总结出以下的Mapping关系:

  1. Root Element被指定为类名。
  2. 不会再Root Element中添加相应的Namaspace。
  3. 对象成员以XML Element的形式输出。
  4. 对象成员出现的顺利和在Type定义的顺序一致。
  5. 只有Public Field和可读可写得Proppery才会被序列化到XML中——比如定义在XMLProduct中的internal string ProducingArea没有出现在XML中。
  6. Type定义的时候不需要运用任何Attribute。

以上这些都是默认的Mapping关系,同DataContractSerializer一样,我们可以通过在Type以及它的成员中运用一些Attribute来改这种默认的Mapping。

  1. Root Element名称之后能为类名。
  2. 可以在Type上运用XMLRoot,通过Namaspace参数在Root Element指定Namespace。
  3. 可以通过在类成员上运用XMLElement Attribute和XMLAttribute Attribute指定对象成员转化成XMLElement还是XMLAttribute。并且可以通过NameSpace参数定义Namespace。
  4. 可以在XMLElement或者XMLAttribute Attribute 通过Order参数指定成员在XML出现的位置。
  5. 可以通过XmlIgnore attribute阻止对象成员被序列化。

基于上面这些,我们重新定义了XMLProduct和XMLOrder。

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace Artech.WCFSerialization
{
    public class XMLProduct
    {
        Private Fields#region Private Fields
        private Guid _productID;
        private string _productName;
        private string _producingArea;
        private double _unitPrice;
        #endregion

        Constructors#region Constructors
        public XMLProduct()
        {
            Console.WriteLine("The constructor of XMLProduct has been invocated!");
        }

        public XMLProduct(Guid id, string name, string producingArea, double price)
        {
            this._productID = id;
            this._productName = name;
            this._producingArea = producingArea;
            this._unitPrice = price;
        }

        #endregion

        Properties#region Properties
        [XmlAttribute("id")]
        public Guid ProductID
        {
            get { return _productID; }
            set { _productID = value; }
        }

        [XmlElement("name")]
        public string ProductName
        {
            get { return _productName; }
            set { _productName = value; }
        }
        [XmlElement("producingArea")]
        public string ProducingArea
        {
            get { return _producingArea; }
            set { _producingArea = value; }
        }

        [XmlElement("price")]
        public double UnitPrice
        {
            get { return _unitPrice; }
            set { _unitPrice = value; }
        }

#endregion

    }
}


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace Artech.WCFSerialization
{
    [XmlRoot(Namespace = "http://artech.wcfSerialization/Samples/Order")]
    public class XMLOrder
    {
        private Guid _orderID;
        private DateTime _orderDate;
        private XMLProduct _product;
        private int _quantity;

        Constructors#region Constructors
        public XMLOrder()
        {
            this._orderID = new Guid();
            this._orderDate = DateTime.MinValue;
            this._quantity = int.MinValue;

            Console.WriteLine("The constructor of XMLOrder has been invocated!");
        }

        public XMLOrder(Guid id, DateTime date, XMLProduct product, int quantity)
        {
            this._orderID = id;
            this._orderDate = date;
            this._product = product;
            this._quantity = quantity;
        }
        #endregion

        Properties#region Properties
        [XmlAttribute("id")]
        public Guid OrderID
        {
            get { return _orderID; }
            set { _orderID = value; }
        }
        [XmlElement(ElementName = "date",Order = 3)]
        public DateTime OrderDate
        {
            get { return _orderDate; }
            set { _orderDate = value; }
        }
        [XmlElement(ElementName = "product", Order = 1, Namespace = "Http://Artech.WCFSerialization/Samples/Product")]
        public XMLProduct Product
        {
            get { return _product; }
            set { _product = value; }
        }

        [XmlElement(ElementName = "quantity", Order = 2)]
        public int Quantity
        {
            get { return _quantity; }
            set { _quantity = value; }
        }
        #endregion

        public override string ToString()
        {
            return string.Format("ID: {0}\nDate:{1}\nProduct:\n\tID:{2}\n\tName:{3}\n\tProducing Area:{4}\n\tPrice:{5}\nQuantity:{6}",
                this._orderID,this._orderDate,this._product.ProductID,this._product.ProductName,this._product.ProducingArea,this._product.UnitPrice,this._quantity);
        }
    }
}


重新进行一次Serialization。我们可以得到下面的XML。

<? xml version="1.0" encoding="utf-8" ?>
< XMLOrder  id ="9a0bbda4-1743-4398-bc4f-ee216e02695b"  xmlns ="http://artech.wcfSerialization/Samples/Order"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd ="http://www.w3.org/2001/XMLSchema" >
  
< product  id ="4e3aabe5-3a51-4000-9fd8-d821d164572a"  xmlns ="Http://Artech.WCFSerialization/Samples/Product" >
    
< name > Dell PC </ name >
    
< producingArea > Xiamen FuJian </ producingArea >
    
< price > 4500 </ price >
  
</ product >
  
< quantity > 300 </ quantity >
  
< date > 2007-03-09T00:00:00+08:00 </ date >
</ XMLOrder >

分析完XMLSerializer的Serialization功能,我们照例来分析它的反向过程—Deserialization。下面的Deserialization的Code。

static void DeserializeViaXMLSerializer()
        {
           string fileName = _basePath + "Order.XmlSerializer.xml";
           XMLOrder order;
           using (FileStream fs = new FileStream(fileName, FileMode.Open))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(XMLOrder), "http://artech.WCFSerialization/Samples");
                using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
                {
                    order= serializer.Deserialize(reader) as XMLOrder;
                }
            }

            Console.WriteLine(order);
            Console.Read();
}


调用DeserializeViaXMLSerializer,得到下面的Screen Shot。下面显示的Order对象的信息和我们利用DataContractSerializaer进行Deserialization是的输出没有什么两样。不过有趣的是上面多出了两行额外的输出:The constructor of XMLProduct has been invocated! The constructor of XMLOrder has been invocated。而这个操作实际上是定义在XMLProduct和XMLOrder的默认(无参)构造函数里的。所此我们可以得出这样的结论——用XMLSerializer进程Deserialization,会调用的默认(无参)构造函数来初始化对象。 

DataContractSerializer V.S. XMLSerializer

上面我们分别分析了两种不同的Serializer,现在我们来简单总结一下他们的区别:

特性

XMLSerializer

DataContractSerializer

默认Mapping

所有Public Field和可读可写Property

所有DataMember Filed、Property

是否需要Attribute

不需要

DataContract DataMember或者Serializable

成员的默认次序

Type中定义的顺序

字母排序

兼容性

.asmx

Remoting

Deserialzation

调用默认构造函数

不会调用

作者: Artech
出处: http://artech.cnblogs.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值