使用ISerializationCallbackReceiver解决HashSet/Dictionary无法序列化的问题

自定义数据类被标记为[Serializable]后, 像 HashSet<T> / Dictionary<T> 类型的数据依然无法被Unity自动序列化。一种办法是内部再存一个数据列表(一般是List<T>类型),序列化之前先把数据倒腾到List<T>中, 在运行时加载后再执行自己写的 "Init()" 之类的函数将数据从List<T>中倒腾到 HashSet<T>中。实际上,对于这种情况,Unity已经提供了一个处理方式: ISerializationCallbackReceiver。自定义的数据类只需要实现这个接口,Unity自己就会在序列化/发序列化时自动执行对应操作。

该接口很简单,在Unity中定义如下:

    [RequiredByNativeCode]
    public interface ISerializationCallbackReceiver
    {
        //
        // 摘要:
        //     Implement this method to receive a callback after Unity deserializes your object. //将在Unity反序列化你的对象后被执行。
        [RequiredByNativeCode]
        void OnAfterDeserialize();
        //
        // 摘要:
        //     Implement this method to receive a callback before Unity serializes your object. //将在Unity序列化你的对象之前被执行。
        [RequiredByNativeCode]
        void OnBeforeSerialize();
    }

当然,并非只有集合类才能这样操作。以下是一段简单的示例代码:

 1 using System.Collections.Generic;
 2 using UnityEngine;
 3 using System;
 4
 5 namespace THP.ExampleCode.SerializationCallback
 6 {
 7     [Serializable] 9     public class Items : ISerializationCallbackReceiver
10     {
11         /// <summary>
12         /// dictionary of items. key: Item.Id value: Item
13         /// </summary>
14         public Dictionary<int, Item> ItemDict = new Dictionary<int, Item>();
15         [SerializeField]
16         List<Item> itemList;
17
18         public void OnAfterDeserialize()
19         {
20             foreach (var item in itemList)
21             {
22                 ItemDict.Add(item.Id, item);
23             }
24         }
25
26         /// <summary>
27         /// 将在序列化之前执行。
28         /// </summary>
29         public void OnBeforeSerialize()
30         {
31             itemList = new List<Item>();
32             foreach (var kv in ItemDict)
33             {
34                 itemList.Add(kv.Value);
35             }
36         }
37     }
38
39     [Serializable]
40     public class Item : ISerializationCallbackReceiver
41     {
42         [NonSerialized]
43         public int Id;
44         [NonSerialized]
45         public string Name;
46         // ... other infos
47         [SerializeField]
48         private byte[] compressedByteArray;
49
50         public void OnAfterDeserialize()
51         {
52             CompressToolAtSomewhere.DecompressItemInfo(compressedByteArray, this);
53         }
54
55         public void OnBeforeSerialize()
56         {
57             compressedByteArray = CompressToolAtSomewhere.CompressItemInfo(this);
58         }
59     }
60 }

原文地址:https://www.cnblogs.com/thpGames/p/10348138.html

时间: 2024-10-10 01:09:55

使用ISerializationCallbackReceiver解决HashSet/Dictionary无法序列化的问题的相关文章

实现Unity对Dictionary的序列化

unity doc: http://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.OnBeforeSerialize.html 1 using UnityEngine; 2 using System.Collections.Generic; 3 4 /// Usage: 5 /// 6 /// [System.Serializable] 7 /// class MyDictionary : Serializable

解决springmvc日期类型序列化

我从数据库查询时间到界面上出来就是毫秒值,经过搜查原来是因为使用rest用JASON去解析,默认会把它转换成long类型格式 知道问题,解决也就简单了,我新建了一个JsonDateSerializer来让它继承JsonSerializer,如下 import java.util.Date; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonProcessingException; import o

解决MVC Json序列化的循环引用问题/EF Json序列化循引用问题---Newtonsoft.Json

1..Net开源Json序列化工具Newtonsoft.Json中提供了解决序列化的循环引用问题: 方式1:指定Json序列化配置为 ReferenceLoopHandling.Ignore 方式2:指定 JsonIgnore忽略 引用对象 实例1,解决MVC的Json序列化引用方法: step1:在项目上添加引用 Newtonsoft.Json程序包,命令:Insert-Package Newtonsoft.Json step2:在项目中添加一个类,继承JsonResult,代码如下: ///

C#序列化与反序列化方式简单总结

相关类: System.SerializableAttribute特性(或称为属性), System.Runtime.Serialization.Iserializable(自定义序列化接口), System.Runtime.Serialization.IserializationSurrogate(自定义序列化代理接口), System.Runtime.Serializatin.SurrogateSelector(自定义序列化代理设置类) 1:官方备注 序列化使用 BinaryFormatte

boost序列化

#include <iostream> #include <boost/serialization/serialization.hpp> #include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/arch

.NET序列化反序列化总结

一直想写这个专题,但是工作后人很懒散,总下不了决心,今天一个人在家就写下来. 关于序列化,可以总结出它的作用有以下几点: 1.记录应用程序的状态,在下次启动时还原上次的状态. 2.进程之间的通信,如使用socket编程时使用.这里的进程包括同一台主机之间进程的通信,也包括不同主机之间的通信. 3.作为对象的深拷贝的一种实现方式. .net中的序列化支持下面几种序列化机制: 1.使可序列化的类型序列化和反序列化 2.控制可序列化的类型的序列化/反序列化内容和过程 3.将类型序列化/反序列化为不同的

对象序列化需要定义serialVersionUID

参见  对象序列化为何要定义serialVersionUID的来龙去脉 若对象序列化后增加了属性,只要serialVersionUID相同,反序列化时根据field的类型预设值反序列化,以解决属性增减对于序列化的兼容性问题.

Spark Task未序列化(Task not serializable)问题分析

问题描述及原因分析 在编写Spark程序中,由于在map等算子内部使用了外部定义的变量和函数,从而引发Task未序列化问题.然而,Spark算子在计算过程中使用外部变量在许多情形下确实在所难免,比如在filter算子根据外部指定的条件进行过滤,map根据相应的配置进行变换等.为了解决上述Task未序列化问题,这里对其进行了研究和总结. 出现"org.apache.spark.SparkException: Task not serializable"这个错误,一般是因为在map.fil

HashMap、LinkedHashMap、HashSet、LinkedHashSet 原理解析及关系梳理

本文以jdk源码为线索学习几种数据类型实现机制. [HashMap数据机制] HashMap提供了key.value存储机制.HashMap是LinkedHashMap的基类,其内部维护一个Node数组用来存储数据: transient Node<K,V>[] table; 为了解决hash冲突,每个节点存储链表或者红黑树.当链表长度小于阈值8时,使用链表存储:当长度达到阈值8时,将链表转换为红黑树提升读写效率: if ((e = p.next) == null) { p.next = new