关于C#中的序列化与反序列化

bubbleblue 2015-03-03 03:54:52
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml;
using System.IO;
using System.Xml.Serialization;


namespace TestDeserialization
{
public class MainClass
{
public MainClass()
{
Initialize();//1
}
private void Initialize()
{
cl1 = new Class1();
cl2 = new Class2();
}
[DataMember(IsRequired = true, EmitDefaultValue = true, Order = 0)]
public Class1 CL1
{
get
{
return cl1;
}

set
{
cl1 = value;

if (cl1 == null)
{
cl1 = new Class1();
}
}
}
[DataMember(IsRequired = true, EmitDefaultValue = true, Order = 1)]
public Class2 CL2
{
get
{
return cl2;
}

set
{
cl2 = value;

if (cl2 == null)
{
cl2 = new Class2();
}
}
}
private Class1 cl1;
private Class2 cl2;

[OnDeserializing()]
public void Initialize(StreamingContext context)
{
Initialize();//4
}
}
public class Class1
{
public Class1()
{
Initialize();//2//5//7
}
private void Initialize()
{
num1 = 1;
bl1 = true;
}
[DataMember(IsRequired = true, EmitDefaultValue = true, Order = 0)]
public int NUM1
{
get
{
return num1;
}

set
{
num1 = value;
}
}
[DataMember(IsRequired = true, EmitDefaultValue = true, Order = 1)]
public bool BL1
{
get
{
return bl1;
}

set
{
bl1 = value;
}
}
private int num1;
private bool bl1;

[OnDeserializing()]
public void Initialize(StreamingContext context)
{
Console.WriteLine(num1);//8
Console.WriteLine(bl1);
}

}
public class Class2
{
public Class2()
{
Initialize();//3//6//9

}
private void Initialize()
{
num2 = 2;
str2 = "Class2string";
}
[DataMember(IsRequired = true, EmitDefaultValue = true, Order = 0)]
public int NUM2
{
get
{
return num2;
}

set
{
num2 = value;
}
}
[DataMember(IsRequired = true, EmitDefaultValue = true, Order = 1)]
public string STR2
{
get
{
return str2;
}

set
{
str2 = value;
}
}
private int num2;
private string str2;

[OnDeserializing()]
public void Initialize(StreamingContext context)
{
Console.WriteLine(num2);//10
Console.WriteLine(str2);

}
}
class Program
{
static void Main(string[] args)
{
string filePath = "d:\\xmlInfo.xml";
//MainClass cls = new MainClass();
//Stream ostrm = File.Open(filePath, FileMode.Create, FileAccess.ReadWrite);

//XmlWriterSettings settings = new XmlWriterSettings();

//settings.Encoding = System.Text.Encoding.UTF8;
//settings.Indent = true;
//settings.CloseOutput = true;

//XmlWriter writer = XmlDictionaryWriter.Create(ostrm, settings);
//DataContractSerializer serializer = new DataContractSerializer(cls.GetType());
//serializer.WriteObject(writer, cls);
//writer.Close();

FileInfo file = new System.IO.FileInfo(filePath);
XmlTextReader reader = new XmlTextReader(file.Open(FileMode.Open, FileAccess.Read));
DataContractSerializer serializer1 = new DataContractSerializer(typeof(MainClass));
MainClass mcls;
mcls = serializer1.ReadObject(reader, false) as MainClass;

Console.ReadLine();

}
}
}

上面注释掉的代码为生成文件的,文件生成后我就注释掉了。
文件如下:
<?xml version="1.0" encoding="utf-8"?>
<MainClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TestDeserialization">
<CL1>
<BL1>true</BL1>
<NUM1>1</NUM1>
</CL1>
<CL2>
<NUM2>2</NUM2>
<STR2>Class2string</STR2>
</CL2>
</MainClass>

Initialize函数后面的数字代表执行顺序。不太明白的是在执行这一步时
mcls = serializer1.ReadObject(reader, false) as MainClass;
先调用MainClass的构造函数,此时Class1与Class2的构造函数先后执行。
再调用MainClass的反序列化函数,此时Class1与Class2的构造函数先后执行。
接下来就有问题了:
Class1与Class2的构造函数又执行了一遍后,才进行了两个类的反序列化函数,这是为什么呢?
也就是说反序列化一个类的时候是一定会先执行一遍该类构造函数才执行反序列化函数么?
...全文
267 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
Class1与Class2的构造函数又执行了一遍后,才进行了两个类的反序列化函数,这是为什么呢? 也就是说反序列化一个类的时候是一定会先执行一遍该类构造函数才执行反序列化函数么? 我的意思是说就是因为你加了那段代码才导致的这种现象,实际上只执行一次构造函数的,要不然问题就大了
bubbleblue 2015-03-03
  • 打赏
  • 举报
回复
引用 4 楼 Z65443344 的回复:
你得在反序列化之后打印mcls的内容啊,不要在初始化的时候打印默认数值
额。。是的, 加了这个属性的反序列化函数也可以打出hello [OnDeserialized()] public void Initialized(StreamingContext context) { Console.WriteLine(num2);//10 Console.WriteLine(str2); }
bubbleblue 2015-03-03
  • 打赏
  • 举报
回复
引用 5 楼 dongxinxi 的回复:
DataContractSerializer或者其他XMLSerializer都一样 都只会调用一次构造函数 你去掉试试 [OnDeserializing()]         public void Initialize(StreamingContext context)         {             Initialize();//4         }
不太明白你的意思额。。我去掉这段代码是为了测试什么?
  • 打赏
  • 举报
回复
DataContractSerializer或者其他XMLSerializer都一样 都只会调用一次构造函数 你去掉试试 [OnDeserializing()]         public void Initialize(StreamingContext context)         {             Initialize();//4         }
於黾 2015-03-03
  • 打赏
  • 举报
回复
你得在反序列化之后打印mcls的内容啊,不要在初始化的时候打印默认数值
bubbleblue 2015-03-03
  • 打赏
  • 举报
回复
引用 2 楼 Z65443344 的回复:
或者你理解成先创建新实例,再用二进制数据填充值也行 具体谁先谁后我也没搞太明白.总之必须创建新实例就是了
<?xml version="1.0" encoding="utf-8"?> <MainClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TestDeserialization"> <CL1> <BL1>true</BL1> <NUM1>1</NUM1> </CL1> <CL2> <NUM2>2</NUM2> <STR2>HELLO</STR2> </CL2> </MainClass> 我把STR2的内容改成上面后,程序还是打印的Class2string,这样子xml文件有什么用呢?
於黾 2015-03-03
  • 打赏
  • 举报
回复
或者你理解成先创建新实例,再用二进制数据填充值也行 具体谁先谁后我也没搞太明白.总之必须创建新实例就是了
於黾 2015-03-03
  • 打赏
  • 举报
回复
mcls = serializer1.ReadObject(reader, false) as MainClass 反序列化会自动将二进制数据反序列化成类,并自动创建一个新实例,那么创建了新实例,当然会走一遍构造函数了

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧