前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >我的WCF之旅(4):WCF中的序列化[上篇]

我的WCF之旅(4):WCF中的序列化[上篇]

作者头像
蒋金楠
发布于 2018-01-16 10:02:16
发布于 2018-01-16 10:02:16
76300
代码可运行
举报
文章被收录于专栏:大内老A大内老A
运行总次数:0
代码可运行

SOA 和Message Windows Communication Foundation (WCF) 是基于面向服务架构(Service Orientation Architecture——SOA)的一种理想的分布式技术(Distributed Technology), 相信在今后在建立基于SOA企业级别的解决方案和进行系统集成方面将会大有作为。一个基于SOA结构的互联系统(Connected System)通常由若干相互独立的子系统(Sub-System)组成,这些子系统可能一个独立的Application,也可能是由若干Application相互集成共同完成一组相关的任务的小系统。这些子系统以一种有效的方式组合、集成为我们听过一种具有综合功能的解决方案。

在一个基于SOA的分布式系统中,各个子系统相互独立又相互关联。说它们的相互独立是因为他们各个都是一个个自治的系统(Autonomous System),可以实行各自的版本策略和部署策略,而这种版本的部署上的变动通常不应该引起系统中其他部分的变动。说它们又彼此关联,则是因为一个子系统所需要的功能往往由其他某个子系统来实现,我们把实现功能的一方称为Service 的提供者(Provider),把使用Service的一方称为客户(Client)。Client依赖于Service的调用,而不失依赖于Service的实现,只要Service的调用方式没有发生改变,Service的实现变动对于Service的使用者来说是完全透明的。在WCF中,我们把Service的调用相关的提取出来即为我们经常说的Contract,Service的提供者和Client之间共享的是Service Contract——而不传统OO概念下的Type。把相对稳定的Service Contract和经常变动的Service Implementation相互分布早就了我们互联系统的松耦合性(Loosely Couple)。

前面我们简单介绍了SOA系统的基本特征——子系统之间的松耦合性(Loosely Couple);各个子系统的自治性(Autonomous);共享Contract。此外SOA还有其他的一些特征,最重要的一个特征就它是一个基于Message(Message-Based)的系统。子系统之间的相互交互由Message来实现。Client向Service的提供者发送一个Soap Message来访为他所需要的Service,Service的提供者监听到来自Client的请求,创建相应的Service对象,执行相关的操作,把执行的结果(Result)以Message 的形式发回给对应的Client。所以我们可以说子系统之间的相互交互本质上是一种消息的交互过程(Message Exchange)。不同的交互方式对应不同的Message Exchange Pattern——MEP。

理解了SO的基本原理,我们来看看WCF,从WCF的全称来分析——Windows Communication Foundation,顾名思义,他就是解决分布式互联系统中各相互独立的子系统如何交互的问题,换句话说,它实际上就是提供 一个基础构架(Infrastructure)实现Application的通信问题。我们前边已经提到,各个子系统之间是通过XML Message进行交互的,所以我们可以 把WCF看成是一个完全处理XML Message的构架,WCF的所有的功能都是围绕着Message来展开的——如何把一个Service的调用转或称一个Message Exchange(Service Contract);如何实现一般的.NET对象和能够容纳于XML Message中的XML Infoset之间的转化(Serialization和Deserialization);如何实现承载数据的XML Infoset和能够用于网络传递的字节流(Byte Stream)之间的相互转化(Encoding和Deconding);如何保证置于Message中数据的一致性和防止被恶意用户窃取以及验证调用Service和通过Service的合法性(Security:Confidentiality,Integrity,Authentication——CIA);如何保证Message被可靠地被传达到所需的地方(Reliable Messaging);以及如何把若干次Service调用——本质上是若干次Message Exchange纳入到一个单独的Conversation(Session Support 和Transaction Support……

在分布式系统中,一个Application与另一个Application之间进行交互,必然需要携带数据。前面我们说了,系统交互完全是应Message的方式进行的,Message是XML,当然置于Message中的数据也应该是XML(XML Infoset)。如何处理这些交互的数据,我们可能首先想到的就是直接处理XML,我们可以在XML级别通过相关的XML技术——XSD,XPath,XSLT来操作数据。但是要使我们处理后的XML需要和要求的完全一致,这样的工作无疑是非常枯燥乏味而且费时费力的。而我们最擅长的就是使用.NET对象来封装我们的数据。如何使我们创造的对象能够有效地转化成结构化的XML Infoset,就是今天我们要讲的内容——Serialization。

Serialization V.S. Encoding

Serialization可以看成是把包含相同内容的数据从一种结构 (.NET Object) 转换成另一种结构 (XML) 。要实现在两种不同结构之间的转化,这两种结构之间必须存在一种Mapping。Serialization的是实现由序列化器(Serializer)来负责。而Serializer则利用某种算法(Arithmetic)来提供这种Mapping。我们知道对于一个Managed Type的结构信息——比如它的所有成员的列表,每个成员的Type、访问限制,以及定在每个成员上的属性,作为原数据被存贮在Assembly的原数据表中,这些原数据可以通过反射的机制获得。而XML的结构一般利用XSD来定义。所以 在WCF中的Serialization可以看成是Serializer通过反射的机制分析对象所对应的Type的原数据,从而提供一种算法实现Managed Type的XSD的转化。

很多刚刚接触WCF的人往往不能很好地区分Serialization和Encoding。我们的.NET Object通过Serialization转化成XML Infoset。但是要使我们的数据能够通过网络协议在网络上传递,必须把生成的XML Infoset转化成字节流(Byte Stream)。所以Encoding关注的是XML Infoset到字节流(Byte Stream)这一段转化的过程。在WCF中,有3中不同的方式可供选择:Binary;Text和MTOM(Message Transmit Optimized Mechanism)。Binary具有最好的Performance,Text具有最好的互操作性,MTOM则有利于大量数据的传送。

我们可以这样来理解Serialization和Encoding,Sterilization是基于Service Contract的——而实际上它也是定义在Service Contract中,是放在我们的Code中;而Encoding一般由Binding提供,它是和Service无关的,我们一般在Configuration中根据实际的需要选择我们合适的Encoding。WCF把Serialization和Encoding相互分离是有好处的,Serialization手部署环境的影响相对不大,具有相对的通用性,而Encoding则关系到访问Service的性能以及互操作性等方面,和部署环境紧密相关。比如对于一个在一个Intranet内部使用的系统,往往处于提高Performance考虑,我们一般是使用TCP Transport结合Binary,可能在某一天出现的来自于Internet的潜在的调用,我们不得不改用Http作为Transport,并使用Text Encoding。由于Encoding是可配置的,所以在这种情况下,我们只需要改变Configuration文件就可以了。

DataContractSerializer

Serialization 是通过Serializer来完成的,在WCF中,我们有3种不同的Serializer——DataContractSerializer(定义在System.RunTime.Serializtion namespace中)、XMLSerializer(定义在System.XML.Serialization namespace)和NetDataContractSerializer (定义在System.XML.Serialization namespace) 。他们不同的方式实现.NET Object的Serialization。由于DataContractSerializer和NetDataContractSerializer基本上没有太大的区别,我们只讨论DataContractSerializer和XMLSerializer。其中DataContractSerializer为WCF默认的Serializer,如果没有显式定采用另外一种Serializer,WCF会创建一个DataContractSerializer 序列化NET Object。首先我们来讨论DataContractSerializer采用怎样的一种Mapping方式来把.NET Object转化成XML。我们照例用实验来说明问题。

我们创建两个类DataContractProduct和DataContractOrder用于表示产品和订单两个实体,读者完全可以命知道描述的内容,这里不作特别的介绍。 

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

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

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

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

        #endregion

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

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

        [DataMember]
        private string ProducingArea
        {
            get { return _producingArea; }
            set { _producingArea = value; }
        }

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

        #endregion

    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

namespace Artech.WCFSerialization
{
    [DataContract]
    [KnownType(typeof(DataContractOrder))]
    public class DataContractOrder
    {
        private Guid _orderID;
        private DateTime _orderDate;
        private DataContractProduct _product;
        private int _quantity;

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

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

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

        Properties#region Properties
        [DataMember]
        public Guid OrderID
        {
            get { return _orderID; }
            set { _orderID = value; }
        }
        [DataMember]
        public DateTime OrderDate
        {
            get { return _orderDate; }
            set { _orderDate = value; }
        }
        [DataMember]
        public DataContractProduct Product
        {
            get { return _product; }
            set { _product = value; }
        }
        [DataMember]
        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);
        }
    }
}

使用DataContractSerializer序列化.NET Object。相关的Type必须运用System.Runtime.Serialization. DataContractAttribute, 需要序列化的成员必须运用System.Runtime.Serialization. DataMemberAttribute。为了使我们能够了解DataContract默认的Mapping机制,我们暂时不在DataContractAttribute和DataMemberAttribute设置任何参数。下面我们 来编写具体的Serialization的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Diagnostics;

namespace Artech.WCFSerialization
{
    class Program
    {
        static string _basePath = @"E:\Projects\Artech.WCFSerialization\Artech.WCFSerialization\";

        static void Main(string[] args)
        {
            SerializeViaDataContractSerializer();
        }
        static void SerializeViaDataContractSerializer()
        {
            DataContractProduct product = new DataContractProduct(Guid.NewGuid(), "Dell PC", "Xiamen FuJian", 4500);
            DataContractOrder order = new DataContractOrder(Guid.NewGuid(), DateTime.Today, product, 300);
            string fileName = _basePath + "Order.DataContractSerializer.xml";
            using (FileStream fs = new FileStream(fileName, FileMode.Create))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(DataContractOrder));
                using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs))
                {
                    serializer.WriteObject(writer, order);
                }
            }
            Process.Start(fileName);
        }
    }
}

代码很简单,这里不作特别介绍。我们现在只关心生成XML是怎样的结构: 

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

1.        Root Element为对象的Type Name——DataContractOrder

2.        Type的Namespace会被加到XML根节点的Namespace中http://schemas.datacontract.org/2004/07/Artech.WCFSerialization

3.        对象的所有成员以XML Element的形式而不是以XML Attribute的形式输出。

4.        所以对象在XML的输出顺序是按照字母排序。

5.        所有成员的Elelement 名称为成员名称。

6.        不论成员设置怎样的作用域(public,protected,internal,甚至市Private),

所有运用了DataMemberAttribute的成员均被序列化到XML中——private string ProducingArea。

7.        Type和成员必须运用DataContractAttribute和DataMemberAttribute才能被序列化。

上面这些都是默认的Mapping关系,在通常情况下我们用默认的这种Mapping往往不能满足我们的需求,为了把.NET序列化成我们需要的XML 结构(比如我们的XmL必须于我们预先定义的XSD一致),我们可以在这两个Attribute(DataContractAttribute和DataMemberAttribute)制定相关的参数来实现。具体做法如下。

1.        Root Element可以通过DataContractAttribute中的Name参数定义。

2.        Namespace可以通过DataContractAttribute中的NameSpace参数定义。

3.        对象的成员只能以XML Element的形式被序列化。

4.        对象成员对应的XML Element在XML出现的位置可以通过DataMemberAttribute的Order参数来定义。

5.        对象成员对应的Element的名称可以通过DataMemberAttribute中的Name定义。

6.        如果不希望某个成员输出到XML中,可以去掉成员对应的DataMemberAttribute Attribute。

此外DataMemberAttribute还有连个额外的参数:

1.         IsRequired:制定该成员为必须的,如果通过工具生成XSD的话,对应的Element的minOccur=“1”

2.        EmitDefaultValue:制定是否输入没有赋值的成员(值为默认值)是否出现在XML中。

基于上面这些,现在我们修改我们的DataContractOrder和DataContractProduct。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

namespace Artech.WCFSerialization
{
    [DataContract(Name = "product", Namespace = "http://Artech.WCFSerialization/Samples/Product")]
    public class DataContractProduct
    {
        Private Fields#region Private Fields
        private Guid _productID;
        private string _productName;
        private string _producingArea;
        private double _unitPrice;
        #endregion

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

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

        #endregion

        Properties#region Properties
        [DataMember(Name ="id",Order = 1)]
        public Guid ProductID
        {
            get { return _productID; }
            set { _productID = value; }
        }

        [DataMember(Name = "name", Order = 2)]
        public string ProductName
        {
            get { return _productName; }
            set { _productName = value; }
        }

        [DataMember(Name = "producingArea", Order = 3)]
        internal string ProducingArea
        {
            get { return _producingArea; }
            set { _producingArea = value; }
        }

        [DataMember(Name = "price", Order = 4)]
        public double UnitPrice
        {
            get { return _unitPrice; }
            set { _unitPrice = value; }
        }

        #endregion

    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

namespace Artech.WCFSerialization
{
    [DataContract(Name ="order",Namespace="http://Artech.WCFSerialization/Samples/Order")]
    public class DataContractOrder
    {
        private Guid _orderID;
        private DateTime _orderDate;
        private DataContractProduct _product;
        private int _quantity;

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

            Console.WriteLine("The constructor of DataContractOrder has been invocated!");
        }    [KnownType(typeof(DataContractOrder))]


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

        Properties#region Properties
        [DataMember(Name ="id",Order =1)]
        public Guid OrderID
        {
            get { return _orderID; }
            set { _orderID = value; }
        }
        [DataMember(Name = "date", Order = 2)]
        public DateTime OrderDate
        {
            get { return _orderDate; }
            set { _orderDate = value; }
        }
        [DataMember(Name = "product", Order = 3)]
        public DataContractProduct Product
        {
            get { return _product; }
            set { _product = value; }
        }
        [DataMember(Name = "quantity", Order = 4)]
        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);
        }
    }
}

再次进行序列化,看看得到的XML是什么样子?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<order xmlns="http://Artech.WCFSerialization/Samples/Order" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <id>994b42c4-7767-4ed4-bdf8-033e99c00a64</id>
  <date>2007-03-09T00:00:00+08:00</date>
  <product xmlns:a="http://Artech.WCFSerialization/Samples/Product">
    <a:id>137e6c34-3758-413e-8f8a-83f26f78a174</a:id>
    <a:name>Dell PC</a:name>
    <a:producingArea>Xiamen FuJian</a:producingArea>
    <a:price>4500</a:price>
  </product>
  <quantity>300</quantity>
</order>

注:对于DataContract Serializer,这里有两点需要我们注意的:

1.         由于Serialization是对数据的不同结构或形态的转化,在转化过程中必须预先知道两种数据相关的原数据(Metadata)。而对于每个.NET对象来说,它的数据结果存放在他所对应的Assembly的原数据表中(Metadata Table),这些原数据表定义的每个定义在该Assembly中的Type的成员定义——包括成员的Type,访问作用域,成员名称,以及运用在成员上的所有Attribute。原则上,只要知道.NET对象对应的Type,我们就可以通过反射(Reflection)的机制分析出该对象的结构。在该例子中,Serializer要序列化DataContractOrder的对象,必须首先知道该对象所属的Type——这个Type通过构造函数传递给Serializer。但是DataContractOrder定义了一个特殊的成员Product,他属于我们的自定义Type:DataContractProduct(这里需要特别指出的是对于.NET的基元类型——Primary Type和一半的常用Type——比如DateTime,Guid等等,Serializer可以自动识别,所以不用特别指定),Serializer是不会识别这个对象的,所以我们需要在定义DataContractOrder的时候运用KnownType Attribute来这个Type。

2.         因为在传统的分布式应用中,我们广泛地采用Serializable Attribute来表明该对象是可以序列化的,DataContract Serializer对这种机制也是支持的。

上面我们讲了Serialization,它的本质就是把.NETObject转化具有一定结构的XML Infoset。被序列化的成的XML Infoset记过Encoding被进一步转化成适合在网络上传递的字节流。当这些字节流从一个Application传递到另一个Application,由于我们的程序的业务逻辑处理的是一个个的.NET对象,所以在目标Application, 会以一个相反的过程把接收到的字节流重构成为和原来一样的.NET Object——目标Application对接收到的字节流记过Decoding转化成XML Infoset,然后通过创建和用于序列化过程一致的Serializer通过Deserialization重建一个.NET Object。所以这就对Serializer提出了要求——它必须为Managed Type的结构和XML的结构提供可逆性的保证——我们把一个.NET Object序列化成一组XML,然后对这组XML进行反序列化重建的对象必须和原来一致。

现在我们在验证这种一致性。在上面的Sample中,我们创建了一个DataContractOrder对象,对它进行序列化并把生成的XML保存的一个文件里面(Order.DataContractSerializer.xml),现在我们都读取这个文件的内容,把它反序列化成DataContractOrder 对象,看它的内容是否和原来一样。下面是Deserialization的逻辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static void DeserializeViaDataContractSerializer()
        {
            string fileName = _basePath + "Order.DataContractSerializer.xml";
            DataContractOrder order;
            using (FileStream fs = new FileStream(fileName, FileMode.Open))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(DataContractOrder));
                using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
                {
                    order = serializer.ReadObject(reader) as DataContractOrder;
                }
            }

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

调用这个方法,通过在控制台输出DataContractOrder的内容,我们可以确定,通过Deserialization生成的DataContractOrder 对象和原来的对象具有一样的内容。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2007-03-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
我的WCF之旅(4):WCF中的序列化[下篇]
XMLSerializer 提到XMLSerializer,我想绝大多数人都知道这是asmx采用的Serializer。首先我们还是来看一个例子,通过比较Managed Type的结构和生成的XML的结构来总结这种序列化方式采用的是怎样的一种Mapping方式。和DataContractSerialzer Sample一样,我们要定义用于序列化对象所属的Type——XMLOrder和XMLProduct,他们和相面对应的DataContractOrder和DataContractProduct具有相同的成
蒋金楠
2018/01/16
6480
我的WCF之旅(4):WCF中的序列化[下篇]
我的WCF之旅(12):使用MSMQ进行Reliable Messaging
在一个分布式的环境中,我们往往需要根据具体的情况采用不同的方式进行数据的传输。比如在一个Intranet内,我们一般通过TCP进行高效的数据通信;而在一个Internet的环境中,我们则通常使用Http进行跨平台的数据交换。而这些通信方式具有一个显著的特点,那就是他们是基于Connection的,也就是说,交互双方在进行通信的时候必须保证有一个可用的Connection存在于他们之间。而在某些时候,比如那些使用拨号连接的用户、以及使用便携式计算机的用户,我们不能保证在他们和需要访问的Server之间有一个的可靠的连接,在这种情况下,基于Messaging Queue的连接就显得尤为重要了。我们今天就来谈谈在WCF中如何使用MSMQ。
蒋金楠
2022/05/09
4410
我的WCF之旅(12):使用MSMQ进行Reliable Messaging
WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)
大部分的系统都是以数据为中心的(Data Central),功能的实现表现在对相关数据的正确处理。而数据本身,是有效信息的载体,在不同的环境具有不同的表示。一个分布式的互联系统关注于数据的交换,而数据正常交换的根本前提是参与数据交换的双方对于数据结构的一致性理解。这就为数据的表现提出了要求,为了保证处于不同平台、不同厂商的应用能够正常地进行数据交换,交换的数据必须采用一种大家都能够理解的展现方式。在这方面,XML无疑是最好的选择。所以WCF下的序列化(Serialization)解决的就是如何将数据从对象的
蒋金楠
2018/01/16
1.7K0
WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)
谈谈WCF中的Data Contract(2):WCF Data Contract对Generic的支持
通过第一部分的介绍,我们可以体会到,WCF 的Data Contract在CLR Type和Neutral Contract之间搭建了一座桥梁,弥合了.NET世界和厂商中立世界的差异。通过WCF Data Contract我们将CLR Data Type暴露成一个厂商中立的数据结构的描述,同样通过WCF Data Contract我们将一个现有的CLR Data Type和既定的Neutral contract进行适配。 在.NET中,基于Primary Type,比如Int32,String等等,他们具有
蒋金楠
2018/01/16
7990
WCF技术剖析之十四:泛型数据契约和集合数据契约(上篇)
在.NET Framework 2.0中,泛型第一次被引入。我们可以定义泛型接口、泛型类型、泛型委托和泛型方法。序列化依赖于真实具体的类型,而泛型则刻意模糊了具体类型概念。而集合代表一组对象的组合,集合具有可迭代(Enumerable)的特性,可以通过某个迭代规则遍历集合中的每一个元素。由于范型类型和集合类型在序列化和反序列化上具有一些特殊的行为和规则,在这篇文章中,我将会对此进行详细介绍。上篇先来说所泛型数据契约。 一、泛型与数据契约 面向对象通过继承实现了代码的重用,而泛型则实现了“算法的重用”。我们
蒋金楠
2018/01/16
1.3K0
谈谈WCF中的Data Contract (1):Data Contract Overview
Contract in SO:Contract是对操作和数据的抽象 在我们看来,Service Orientation提供了一种对业务、功能进行分解的方式。针对SO,我们把一个具体的业务流程或者一个复杂的功能分解成一个个独立完成某项任务的子单元,这些子单元通过一个个Service来承载。对于Service本身来讲,他们应该是自治的,独自完成自己的功能、不依赖于其他的Service。但是Service的价值体现在它被潜在的消费者使用的程度。这实际上包含两方面的内容,作为Service本身,它如何将自己暴露出来
蒋金楠
2018/02/07
6500
WCF技术剖析之十三:序列化过程中的已知类型(Known Type)
DataContractSerializer承载着所有数据契约对象的序列化和反序列化操作。在上面一篇文章(《数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)》)中,我们谈到DataContractSerializer基本的序列化规则;如何控制DataContractSerializer序列化或者反序列化对象的数量;以及如何在序列化后的XML中保存被序列化对象的对象引用结构。在这篇文章中,我们会详细讨论WCF序列化中一个重要的话题:已知类型(Known
蒋金楠
2018/01/16
1K0
WCF技术剖析之十三:序列化过程中的已知类型(Known Type)
谈谈WCF中的Data Contract(4):WCF Data Contract Versioning
软件工程是一门独特的工程艺术,需要解决的是不断改变的需求变化。而对于WCF,对于SOA,由于涉及的是对多个系统之间的交互问题,如何有效地解决不断改变的需求所带来的问题就显得更为重要:Service端版本的变化能否保持现有Consumer的正常调用,Consumer端的改变不至于影响对Service 的正常调用。对于Data Contract来说就是要解决这样的问题:Service端或者Client对Data Type的改变不会影响Service的正常调用。 在系统开发过程中,通过对Data Type添加额外
蒋金楠
2018/01/16
8120
谈谈WCF中的Data Contract(4):WCF Data Contract Versioning
一个关于解决序列化问题的编程技巧
在前一篇文章中我曾经说过,现在正在做一个小小的框架以实现采用统一的API实现对上下文(Context)信息的统一管理。这个框架同时支持Web和GUI应用,并支持跨线程传递和跨域传递(这里指在WCF服务调用中实现客户端到服务端隐式传递),以及对上下文项目(ContextItem)的读写控制。关键就在于后面两个特性的支持上面,出现一个小小的关于序列化的问题。解决方案只需要改动短短的一行代码,结果却让我折腾了老半天。 一、问题重现 为了重现我实际遇到的问题,我特意将问题简化,为此我写了一个简单的例子(你可以从这里
蒋金楠
2018/01/16
7150
一个关于解决序列化问题的编程技巧
WCF版的PetShop之二:模块中的层次划分[提供源代码下载]
上一篇文章主要讨论的是PetShop的模块划分,在这一篇文章中我们来讨论在一个模块中如何进行层次划分。模块划分应该是基于功能的,一个模块可以看成是服务于某项功能的所有资源的集合;层次划分侧重于关注点分离(SoC:Separation of Concern ),让某一层专注于某项单一的操作,以实现重用性、可维护性、可测试性等相应的目的。Source Code从这里下载。 一、基本的层次结构 我们接下来将目光聚焦到模块内部,看看每一个模块具体又有怎样的层次划分。我们将Infrastructures、Produc
蒋金楠
2018/01/16
1.3K0
WCF版的PetShop之二:模块中的层次划分[提供源代码下载]
WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化
在本篇文章中,我们将讨论WCF四大契约(服务契约、数据契约、消息契约和错误契约)之一的消息契约(Message Contract)。服务契约关注于对服务操作的描述,数据契约关注于对于数据结构和格式的描述,而消息契约关注的是类型成员与消息元素的匹配关系。 我们知道只有可序列化的对象才能通过服务调用在客户端和服务端之间进行传递。到目前为止,我们知道的可序列化类型有两种:一种是应用了System.SerializableAttribute特性或者实现了System.Runtime.Serialization.I
蒋金楠
2018/01/16
1.7K0
WCF技术剖析之十六:数据契约的等效性和版本控制
数据契约是对用于交换的数据结构的描述,是数据序列化和反序列化的依据。在一个WCF应用中,客户端和服务端必须通过等效的数据契约方能进行有效的数据交换。随着时间的推移,不可避免地,我们会面临着数据契约版本的变化,比如数据成员的添加和删除、成员名称或者命名空间的修正等,如何避免数据契约这种版本的变化对客户端现有程序造成影响,就是本节着重要讨论的问题。 一、数据契约的等效性 数据契约就是采用一种厂商中立、平台无关的形式(XSD)定义了数据的结构,而WCF通过DataContractAttribute和DataMe
蒋金楠
2018/01/16
8930
WCF技术剖析之十六:数据契约的等效性和版本控制
谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持
在本篇文章上一部分Order Processing的例子中,我们看到原本已Collection形式定义的DetailList属性(public IList<TDetail> DetailList),在Data Contract中却以Array的方式体现(public OrderDetail[] DetailList)。我们现在就来详细地讨论一下基于Collection & Dictionary 的Data Contract。 Data Contract for Collection 我们照例用例子来说
蒋金楠
2018/01/16
7040
谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持
WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用
如果一个类型,不一定是数据契约,和给定的数据契约具有很大的差异,而我们要将该类型的对象序列化成基于数据契约对应的XML。反之,对于一段给定的基于数据契约的XML,要通过反序列化生成该类型的对象,我们该如何实现这样的场景? 比如下面定义了两个类型Contact和Customer,其中Customer是数据契约,Contact的Sex属性相当于Customer的Gender属性,而Contact的FullName可以看成是Customer的FirstName和LastName的组合。现在我们要做的是将一个Co
蒋金楠
2018/01/16
8560
我的WCF之旅(10):如何在WCF进行Exception Handling
在任何Application的开发中,对不可预知的异常进行troubleshooting时,异常处理显得尤为重要。对于一般的.NET系统来说,我们简单地借助try/catch可以很容易地实现这一功能。但是对于 一个分布式的环境来说,异常处理就没有那么简单了。按照面向服务的原则,我们把一些可复用的业务逻辑以Service的形式实现,各个Service处于一个自治的环境中,一个Service需要和另一个Service进行交互,只需要获得该Service的描述(Description)就可以了(比如WSDL,Sc
蒋金楠
2018/02/07
5530
我的WCF之旅(10):如何在WCF进行Exception Handling
我的WCF之旅(13):创建基于MSMQ的Responsive Service
一、One-way MEP V.S. Responsible Service 我们知道MSMQ天生就具有异步的特性,它只能以One-way的MEP(Message Exchange Pattern)进
蒋金楠
2018/02/07
7670
我的WCF之旅(13):创建基于MSMQ的Responsive Service
WCF技术剖析之十七:消息(Message)详解(上篇)
消息交换是WCF进行通信的唯一手段,通过方法调用(Method Call)形式体现的服务访问需要转化成具体的消息,并通过相应的编码(Encoding)才能通过传输通道发送到服务端;服务操作执行的结果也只能以消息的形式才能被正常地返回到客户端。所以,消息在整个WCF体系结构中处于一个核心的地位,WCF可以看成是一个消息处理的管道。 尽管消息在整个WCF体系中具有如此重要的意义,可是一般的WCF编程人员,却意识不到消息的存在。原因很简单,WCF设计的目标就是实现消息通信的所有细节,为最终的编程人员提供一个完全
蒋金楠
2018/01/16
2.7K0
WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]
元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框架体系中,元数据的导出工作由MetadataExporter实现。MetadataExporter是一个抽象类型,定义了导出元数据的基本行为。WCF定义一个具体的MetadataExporter:WsdlExporter,将基于某个终结点的元数据导出生成基于WSDL的MetadataSet。我们先来认识MetadataExporter和MetadataSet。 一、MetadataExporte
蒋金楠
2018/01/16
7760
WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]
WCF技术剖析之二十一:WCF基本异常处理模式[下篇]
从FaultContractAttribute的定义我们可以看出,该特性可以在同一个目标对象上面多次应用(AllowMultiple = true)。这也很好理解:对于同一个服务操作,可能具有不同的异常场景,在不同的情况下,需要抛出不同的异常。 1: [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] 2: public sealed class FaultContractAttri
蒋金楠
2018/01/16
6250
WCF技术剖析之二十一:WCF基本异常处理模式[下篇]
WCF技术剖析之二十一: WCF基本的异常处理模式[上篇]
由于WCF采用.NET托管语言(C#和NET)作为其主要的编程语言,注定以了基于WCF的编程方式不可能很复杂。同时,WCF设计的一个目的就是提供基于非业务逻辑的通信实现,为编程人员提供一套简单易用的应用编程接口(API)。WCF编程模式的简单性同样体现在异常处理上面,本篇文章的主要目的就是对WCF基于异常处理的编程模式做一个简单的介绍。 一、当异常从服务端抛出 对于一个典型的WCF服务调用,我个人倾向于将潜在抛出的异常费为两种类型:应用异常(Application Exception)和基础结构(Infr
蒋金楠
2018/01/16
8080
WCF技术剖析之二十一: WCF基本的异常处理模式[上篇]
推荐阅读
我的WCF之旅(4):WCF中的序列化[下篇]
6480
我的WCF之旅(12):使用MSMQ进行Reliable Messaging
4410
WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)
1.7K0
谈谈WCF中的Data Contract(2):WCF Data Contract对Generic的支持
7990
WCF技术剖析之十四:泛型数据契约和集合数据契约(上篇)
1.3K0
谈谈WCF中的Data Contract (1):Data Contract Overview
6500
WCF技术剖析之十三:序列化过程中的已知类型(Known Type)
1K0
谈谈WCF中的Data Contract(4):WCF Data Contract Versioning
8120
一个关于解决序列化问题的编程技巧
7150
WCF版的PetShop之二:模块中的层次划分[提供源代码下载]
1.3K0
WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化
1.7K0
WCF技术剖析之十六:数据契约的等效性和版本控制
8930
谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持
7040
WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用
8560
我的WCF之旅(10):如何在WCF进行Exception Handling
5530
我的WCF之旅(13):创建基于MSMQ的Responsive Service
7670
WCF技术剖析之十七:消息(Message)详解(上篇)
2.7K0
WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]
7760
WCF技术剖析之二十一:WCF基本异常处理模式[下篇]
6250
WCF技术剖析之二十一: WCF基本的异常处理模式[上篇]
8080
相关推荐
我的WCF之旅(4):WCF中的序列化[下篇]
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文