C#序列化
序列化是将对象或对象图转换成字节流的过程。反序列化是将字节流转换回对象图的过程。序列化可以用于应用程序状态的保存、剪贴板复制/粘贴对象、对象克隆和网络对象传输等。序列化的方式有:
1) BinaryFormatter 早期的序列化方式,存在安全风险,不推荐使用。
2) BinaryReader/BinaryWriter 二进制读写Primitive Type,并支持字符串读写时的编码设定。
3) XML序列化
4) Json序列化 除了MS提供的库外,Newtonsoft.json非常好用。
因为BinaryFormatter存在大量的存量使用,做个简单记录。使对象能够通过BinaryFormatter序列化有特性和接口两种实现方式。当特性和接口同时使用时,忽略特性。接口对数据进行完全的控制,且避免使用反射。
1、通过特性实现
[Serializable]
class Circle
{
private double _radius;
[NonSerialized]
private double _area;
public Circle(double radius)
{
_radius = radius;
_area = Math.PI * _radius * _radius;
}
public double Area
{
get => _area;
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
_area = Math.PI * _radius * _radius;
}
}
class Program
{
static void Main(string[] args)
{
Circle circle = new(1.2);
Stream stream = SerializeToMemory(circle);
stream.Position = 0;
circle = (Circle)DeserializeFromMemory(stream);
}
static Stream SerializeToMemory(Circle circle)
{
MemoryStream stream = new();
BinaryFormatter bf = new();
bf.Serialize(stream, circle);
return stream;
}
static object DeserializeFromMemory(Stream stream)
{
BinaryFormatter bf = new();
return bf.Deserialize(stream);
}
}
2、通过接口
除了接口之外,大多数类型还实现了一个特殊的构造器。
[Serializable]
class Circle : ISerializable, IDeserializationCallback
{
private double _radius;
private double _area;
public Circle(double radius)
{
_radius = radius;
_area = Math.PI * _radius * _radius;
}
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter =true)]
private Circle(SerializationInfo info, StreamingContext context)
{
_radius = info.GetDouble("radius");
}
public double Area
{
get => _area;
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("radius", _radius);
}
public void OnDeserialization(object sender)
{
_area = Math.PI * _radius * _radius;
}
}
class Program
{
static void Main(string[] args)
{
Circle circle = new(1.2);
Stream stream = SerializeToMemory(circle);
stream.Position = 0;
circle = (Circle)DeserializeFromMemory(stream);
}
static Stream SerializeToMemory(Circle circle)
{
MemoryStream stream = new();
BinaryFormatter bf = new();
bf.Serialize(stream, circle);
return stream;
}
static object DeserializeFromMemory(Stream stream)
{
BinaryFormatter bf = new();
return bf.Deserialize(stream);
}
}
参考:
《CLR via C#》
Deserialization risks in use of BinaryFormatter and related types | Microsoft Docs