惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

博客园 - windwolf

NHibernate的Decimal数据精度问题,急啊 最近M$发布了好多东东(我感兴趣的...) 对C#的一点抱怨 也谈WCF的序列化 开辟《WF本质论》专栏,以供同好探讨 petshop笔记 map,area标签 - windwolf - 博客园 Windows Workflow Foundation之旅(八)——使用活动控制流程、在工作流中使用条件 家里被洗劫。。。 Windows Workflow Foundation之旅(七)——顺序工作流、状态机工作流 Aspect#是怎么工作的? OO设计原则 Windows Workflow Foundation之旅(六)——框架组成、工作流创作模式 Windows Workflow Foundation之旅(五)——指南3(创建自定义活动) 微软中国最近的两个webcasts Windows workflow foundation之旅(四)——指南2(创建状态机工作流)(下) Windows workflow foundation之旅(三)——指南2(创建状态机工作流)(上) Windows Workflow Foundation之旅(二)——指南1(创建顺序工作流) Windows Workflow Foundation之旅(一)——概况
也谈WCF序列化(续)
windwolf · 2007-09-03 · via 博客园 - windwolf


本篇是上篇的续,如果各位看官不妨从上篇看起,点此进入上篇

上篇说到使用NetDataContractSerializer序列化对象时,会在xml上添加许多附加的attribute。这些attribute有一部分是为了完善序列化后内容的类型信息,比如z:Type和z:Assembly,而另一个作用鄙人买了个关子,留到这回来解释了~。

还是用示例来开篇吧。在这里对上回的示例做一些扩展:

namespace ServiceInterface
{
   [DataContract]
   
public class Sub
   
{
      
public Sub()
      
{ }
     
      
public Sub(int id, string name)
      
{
         Id 
= id;
         Name 
= name;
      }


      [DataMember]
      
public int Id;

      [DataMember]
      
public string Name;

   }


   [DataContract]
   
public class Root
   
{
      
public Root()
      
{ }
      
public Root(int id, string name, Sub sub)
      
{
         Id 
= id;
         Name 
= name;
         Sub1 
= sub;
         Sub2 
= sub;
      }


      [DataMember]
      
public int Id;

      [DataMember]
      
public string Name;

      [DataMember]
      
public Sub Sub1;

      [DataMember]
      
public Sub Sub2;

   }

}

相比上回的示例,这里多了一个Root类,而这个Root类又有两个成员Sub1,Sub2,都是Sub类型了。这是作甚?接着看就明白了~

还是先用DataContractSerializer来序列化Root对象,但这回于上回有些不同,序列化之后,还把它反序列化回来了:

         Sub sub = new Sub(10"ten"); 
         Root root 
= new Root(100"root", sub);

         DataContractSerializer dcs 
= new DataContractSerializer(typeof(Root));
         MemoryStream stream 
= new MemoryStream();

         dcs.WriteObject(stream, root);

         
byte[] buf = stream.ToArray();
         
string str = Encoding.UTF8.GetString(buf, 0, buf.Length);

         stream.Seek(
0, SeekOrigin.Begin);
         Root rt1 
= (Root)dcs.ReadObject(stream);

执行上面这段代码可以发现序列化后的内容为:

<Root xmlns="http://schemas.datacontract.org/2004/07/ServiceInterface" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
<Id>100</Id> 
<Name>root</Name> 
<Sub1> 
<Id>10</Id> 
<Name>ten</Name> 
</Sub1> 
<Sub2> 
<Id>10</Id> 
<Name>ten</Name> 
</Sub2> 
</Root>

而反序列化后呢?细心XD可能已经看出了点端倪~什么?你没发现?再step debug一遍看看?

对了!在序列化之前Root对象的Sub1和Sub2引用的是同一个Sub对象,而反序列化之后,这个field变成分别引用两个不同对象了(虽然内容完全相同)!这还得了!!在讲究原汁原味的今天,怎么能容忍这种事的发生!这可不是俺夸大其词,假如有这么种情况,Root对象有对Sub的引用,而Sub又有对Root对象的引用,到循环引用出现时,DataContractSerializer就没法处理这种情况了。这时NetDataContractSerializer就有了用武之地。

到这里,读者们估计能猜出上回没有解释的z:Id是何用意了。没错,它就是用来解决对象引用问题的。对上文中的Root对象使用NetDataContractSerializer来序列化,并反序列化:

         NetDataContractSerializer ndcs = new NetDataContractSerializer();
         MemoryStream nstream 
= new MemoryStream();

         ndcs.WriteObject(nstream, root);

         
byte[] nbuf = nstream.ToArray();
         
string nstr = Encoding.UTF8.GetString(nbuf, 0, nbuf.Length);

         nstream.Seek(
0, SeekOrigin.Begin);
         Root rt2 
= (Root)ndcs.ReadObject(nstream);

序列化后的xml为:

<Root z:Id="1" z:Type="ServiceInterface.Root" z:Assembly="ServiceInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns="http://schemas.datacontract.org/2004/07/ServiceInterface" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> 
<Id>100</Id> 
<Name z:Id="2">root</Name> 
<Sub1 z:Id="3"> 
<Id>10</Id> 
<Name z:Id="4">ten</Name> 
</Sub1> 
<Sub2 z:Ref="3" i:nil="true" /> 
</Root>

这回,反序列化后的对象可以说无论在形式上还是语义上都与原对象一致了。它是怎么做到的呢?注意看,Sub2元素的中z:Ref为3,而Sub1元素z:Id的值为3。这意味着:反系列化过程会为Sub1创建一个对象,而Sub2仅仅只会引用Sub1。最后还要指出一点,NetDataContractSerializer会为每个引用类型的对象分配一个z:Id。

关于WCF序列化的讨论先到这里,但我知道,这仅仅是个开始~