序列化

本文介绍了C#常见的三种序列化方式,包括BinaryFormatter、SoapFormatter和XML,阐述了序列化和反序列化的作用、要求。还提及选择性序列化和自定义序列化,如使用NonSerialized和ISerializable接口。最后总结了相关方式、属性和接口,提醒序列化不在主线程运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

序列化:将对象保存到文件或数据库(虚的->实质)

反序列化:从文件数据中转化为原来对象(实质->虚的)

C#常见的序列化有三种:BinaryFormatter、SoapFormatter、XML

作用

  • 进程下次启动读取上次保存的对象信息
  • 不同进程间传递数据

要求

  1. public类型或者有[SerializeField]属性
  2. 不是static、const、readonly
  3. 类型必须是Unity可以序列化的类型

实例

  • BinaryFormatter

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.IO;
    using System;
    
    public class Test : MonoBehaviour
    {
        void Start()
        {
            SerializeToFile();
        }
    
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                SerializeFromFile();
            }
        }
    
      void SerializeToFile()
        {
            MyObj obj = new MyObj();
            obj.Id = 1;
            obj.Count = 1;
            obj.Name = "obj";
    
            BinaryFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("Myfile.bin", FileMode.Create, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, obj);
            stream.Close();
        }
        
        void SerializeFromFile()
        {
            BinaryFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("Myfile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
            MyObj obj = (MyObj)formatter.Deserialize(stream);
            stream.Close();
    
            Debug.LogError( "id:" + obj.Id+"\n"+
                            "count:"+obj.Count+"\n"+
                            "name:"+obj.Name              
                );
        }
    }
    
    [Serializable]
    public class MyObj
    {
        public int Id;
        public int Count;
        public string Name;
    }
    1. 添加Serializable属性使类可序列化
    2. 效率很高,能生成非常紧凑的字节流
    3. 反序列化时不调用构造函数
    4. 子类无法继承Serializable属性
  • SoapFormatter

    代码类似 将BinaryFormatter改为SoapFormatter 将Myfile.bin改为Myfile.soap

    1. Soap文件(简单对象访问协议)是一种轻量的、简单的、基于XML的协议,主要用于WEB交互
  • XML

    代码类似 将BinaryFormatter改为XmlSerializer 将Myfile.bin改为Myfile.xml

选择性序列化

NonSerialized:类可能包含不应被序列化的字段。如,某个类的一个成员变量存储着线程ID,当被反序列化时,可能线程不运行,那么这个值反序列化就没有意义

[Serializable]
public class MyObj
{
    public int Id;
    [NonSerialized]
    public int Count;
    public string Name;
}

输出Count=0

自定义序列化

有一种情况是这样:序列化好了一个文件,可是没注意文件损坏,反序列化时就会出错

ISerializable :实现此接口的对象可以自定义序列化过程,在反序列化失效时尤其有用,需要先为变量提供值以保证可以重建对象的完整状态

序列化时需要实现GetObjectData 方法,反序列化时需要用到一个特殊的构造函数

[Serializable]
public class MyObj : ISerializable
{
    public int Id;
    public int Count;
    public string Name;
    public MyObj() { }
    
    //实现接口方法
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("a1", Id);
        info.AddValue("a2", Count);
        info.AddValue("a3", Name);
    }

    //构造函数
    private MyObj(SerializationInfo info, StreamingContext context)
    {
        Id = info.GetInt32("a1");
        Count = info.GetInt32("a2");
        Name = info.GetString("a3");
    }
}

其中,value键值对名称只要对应就可以

总结

  1. 三种方式 BinaryFormatter、SoapFormatter、XML
  2. 三个属性 Serializable、NonSerialized、SerializeField
  3. 一个接口 ISerializable
  4. 要小心使用序列化,因为序列化并不是运行在主线程!

参考

https://www.cnblogs.com/devhyj/p/4342592.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值