序列化反序列化C# Unity数据类暴露在Inspect

版权声明:转载 请说明出处 https://blog.csdn.net/qq2512667/article/details/89432353

序列化

序列化
(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
序列化使其他代码可以查看或修改,那些不序列化便无法访问的对象实例数据。确切地说,代码执行序列化需要特殊的权限:即指定了
SerializationFormatter 标志的 SecurityPermission。在默认策略下,通过 Internet
下载的代码或 Internet 代码不会授予该权限;只有本地计算机上的代码才被授予该权限。

在C中关键字是Serializable 表示序列化特性
它应用于 类型 用来告诉格式化程序一个类型的实例的字段 可以进行序列化和反序列化操作。
比如 做编辑器扩展, 需要快速添加数据, 想要暴露 一个数据类,则可以在数据类前 添加[Serializable] 特性

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Serializable
{
    public string name;
    public int age;
    public bool isHero;
    public Serializable(string name,int age,bool isHero)
    {
        this.name = name;
        this.age = age;
        this.isHero = isHero;

    }
    
    public Hero hero;
    [System.Serializable]
    public class Hero
    {
        public int Attack;
        public int Speed;
    }
}
public class Serializable_205 : MonoBehaviour
{
     
    public Serializable serializable;
     
}

下面用书添加链接描述 上的例子来观察 序列化和反序列 化的过程,

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;

/// <summary>
/// 序列化过程
/// </summary>
public class SerializableTest : MonoBehaviour
{
    public Serializable Serializable;
    // Start is called before the first frame update
    void Start()
    {
        this.Serializable=new Serializable("zeb",22,true);
    }

    private void OnGUI()
    {
        if (GUI.Button(new Rect(10,10,150,100), "Serializable"))
        {
            string fileName = "/Users/fanyou/egg/Assets/Serializable.dat";
           
            Stream fStream=new FileStream(fileName,FileMode.Create,FileAccess.ReadWrite);

            BinaryFormatter   BinFormat=new BinaryFormatter();//创建二进制 序列化器
            //序列化                                                                   
            BinFormat.Serialize(fStream,this.Serializable);
            fStream.Close();
            this.Serializable.name = "yanliang";
            Debug.Log("the Class name is :"+this.Serializable.name);
        }
        if (GUI.Button(new Rect(300, 10, 150, 100), "Deserialize"))
        {
            string fileName = "/Users/fanyou/egg/Assets/Serializable.dat";
           
            Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            
            BinaryFormatter BinFormat = new BinaryFormatter();//创建二进制 序列化器

            //反序列化
           this.Serializable=  BinFormat.Deserialize(fStream) as Serializable;
            fStream.Close();
             
            Debug.Log("after Deserialize the Class name is :" + this.Serializable.name);
        }
    }
}

BinaryFormatter BinFormat=new BinaryFormatter();//创建二进制 序列化器
BinFormat.Serialize(fStream,this.Serializable); 将一个类的实例序列化 也就是写入 文件里,
写入之后, 修改实例 会去影响 序列化之后的数据。
所以反序列化后 ,该类实例名字还是原先的名字。

在这里插入图片描述
它 可以用 序列化 类 结构体,枚举 委托。
serialzableAttribute不可以被继承
另外 特性 类的 自定义 规则 是这样的, 后缀 为Attribute
继承自System.Attribute, 使用的会 ,会自动省去Attribute
在这里插入图片描述
在这里插入图片描述
下面说说 二进制序列化器 序列化的方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
序列化在Unity中可以 理解为在Unity中初始化。

另外 Attribute 类是继承自_Attribute接口的
在这里插入图片描述
所有 特性都需要 继承 Attribute特性类,
在运行的时候,会通过反射 取得 methodInfo TypeInfo 那些, 来检测特性的存在

在这里插入图片描述
在这里插入图片描述

符合公共语言规范(CLS)

CLS

MSDN

下面是_Attribute接口

 /// <summary>
  ///   公开 <see cref="T:System.Attribute" /> 向非托管代码。
  /// </summary>
  [Guid("917B14D0-2D9E-38B8-92A9-381ACF52F7C0")]
  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  [CLSCompliant(false)]
  [TypeLibImportClass(typeof (Attribute))]
  [ComVisible(true)]
  public interface _Attribute
  {
    /// <summary>检索对象提供的类型信息接口的数量(0 或 1)。</summary>
    /// <param name="pcTInfo">
    ///   此方法返回时包含一个用于接收对象提供的类型信息接口数量的位置指针。
    ///    此参数未经初始化即被传递。
    /// </param>
    void GetTypeInfoCount(out uint pcTInfo);

    /// <summary>检索对象的类型信息,然后可以使用该信息获取接口的类型信息。</summary>
    /// <param name="iTInfo">要返回的类型信息。</param>
    /// <param name="lcid">类型信息的区域设置标识符。</param>
    /// <param name="ppTInfo">指向请求的类型信息对象的指针。</param>
    void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);

    /// <summary>将一组名称映射为对应的一组调度标识符。</summary>
    /// <param name="riid">
    ///   留待将来使用。
    ///    必须为 IID_NULL。
    /// </param>
    /// <param name="rgszNames">要映射的名称的数组。</param>
    /// <param name="cNames">要映射的名称的计数。</param>
    /// <param name="lcid">要在其中解释名称的区域设置上下文。</param>
    /// <param name="rgDispId">由调用方分配的数组,它接收与名称对应的标识符。</param>
    void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);

    /// <summary>提供对某一对象公开的属性和方法的访问。</summary>
    /// <param name="dispIdMember">成员的标识符。</param>
    /// <param name="riid">
    ///   留待将来使用。
    ///    必须为 IID_NULL。
    /// </param>
    /// <param name="lcid">要在其中解释参数的区域设置上下文。</param>
    /// <param name="wFlags">描述调用的上下文的标志。</param>
    /// <param name="pDispParams">
    ///   指向包含参数的数组,数组的命名的参数以及每个数组中元素的数目的人数 dispid 的结构的指针。
    /// </param>
    /// <param name="pVarResult">指向将存储结果的位置的指针。</param>
    /// <param name="pExcepInfo">指向一个包含异常信息的结构的指针。</param>
    /// <param name="puArgErr">第一个出错自变量的索引。</param>
    void Invoke(
      uint dispIdMember,
      [In] ref Guid riid,
      uint lcid,
      short wFlags,
      IntPtr pDispParams,
      IntPtr pVarResult,
      IntPtr pExcepInfo,
      IntPtr puArgErr);
  }

猜你喜欢

转载自blog.csdn.net/qq2512667/article/details/89432353