今天在写程序的时候,想要保存一些对象。最初设计时的想法是才用xml来保存。
实际编程过程中发现这还是挺繁琐的,那么多的字段和属性,还有各种组合的类。如果用xml来保存,嵌套多,嫌麻烦!
最重要的是,我觉得使用XML来保存东西的话,那程序就被写死了,在保存/读取的时候,必须依据指定的元素的名或者属性名什么的来操作。如果使用序列化,那所有的一切交给Serialzer来做就搞定了。我们只需要写很少的代码就可以完成这个工作。
然后考虑使用xml序列化来保存,但是这XmlSerialzer只能保存公共字段,感觉有些不够,就用二进制序列化了。对于某个需要进行序列化工作的类,在不继承自接口ISerializable的情况下,通过增加[Serializable]属性可以允许该类可以被序列化,如:
[Serializable]
public class Car
{
private ArrayList _wheels=new ArrayList();
private ArrayList _Lights=new ArrayList();
public ArrayList Wheels
{
get{
return _wheels;
}
set{
_wheels=value;
}
}
public ArrayList Lights
{
get{
return _Lights;
}
set{
_Lights=value;
}
}
public Car
{
Wheel LeftWheel=new Wheel();
Wheel RightWheel=new Wheel();
_wheels.Add(LeftWheel);
_wheels.Add(RightWheel);
Light LeftLight=new Light();
Light RightLight=new Light();
_Lights.Add(LeftLight);
_Lights.Add(RightLight);
}
}
[Serialzable]
public class Wheel
{
public float Radius=0.5f;
}
[Serailzable]
public class Light
{
public float Price=200f;
}
序列化操作:
Car myCar=new Car();
FileStream fs=null;
try
{
FileStream fs=new FileStream(@"../../Test.dat",FileMode.Create);
BinaryFormatter bf=new BinaryFormatter();
bf.Serialize(fs,myCar);
}
catch(Exception e)
{
Messagebox.Show(e.Message);
}
finally
{
if(fs!=null)
fs.Close();
}
ArrayList是支持序列化的,通过以上操作,myCar实例的数据都被保存到了Test.dat中。
如果需要加载,则只需要反序列化:
Car myCar=(Car)bf.Deserialize(fs);
对于多重继承情况,使用序列化还是很方便的,尽管看起来比较傻。
子类的序列化操作在父类里完成,由于不可能给this赋值,所以再在子类里操作父类里没有的字段。
如Car的父类,Vehicle
public abstract class Vehicle
{
private float _Weight;
private float _Height;
private float _Length;
public float Weight
{
get{return _Weight;}
set{_Weight=value;}
}
public float Height
{
get{return _Height;}
set{_Height=value;}
}
public float Length
{
get{retrun _Length;}
set{_Length=value;}
}
//在这里反序列化
public virtual Vehicle LoadFromFile(string filename)
{
//反序列化后给属性赋值
obj=(Vehicle)bf.Deserialze(fs);
_Weight=obj.Weight;
_Length=obj.Length;
_Height=obj.Height;
return (Vehicle)obj;
}
}
在子类Car里
public override Vehicle LoadFromFile(string filename)
{
//如果可以this=(Car)base.LoadFromFile(filename);那就好了,可以省很多。
Car car=(Car)base.LoadFromFile(filename);
_Wheels=car.Wheels;
_Lights=car.Lights;
return null;
}
子类Track
public override Vehicle LoadFromFile(string filename)
{
Track track=(Track)base.LoadFromFile(filename);
_Capacity=track.Capacity;
}
有了这些,在构造函数中,就可以直接从文件中加载了。
public Car()
{
}
public Car(string filename)
{
LoadFromFile(filename);
}
对于某些不支持序列化操作的对象或者结构,MSDN中说Serialzer会自动辨别,只要无法序列化,会自动标记成
[NonSerialzable],通过实际操作,发现还是需要手工标记。如:
[NonSerialzable]
private Microsoft.DirectX.Direct3D.Device pDevice;
如果对象里的不可序列化字段占据了绝大部分,那也就没有什么必要进行序列化了。