4.反射存储常用成员数据

4.反射存储常用成员数据


4.1 知识点

存储数据方法内,获取传入数据对象的所有字段

//获得传进来的data的Type
Type dataType = data.GetType();
//得到dataType的所有字段的数组
FieldInfo[] infos = dataType.GetFields();

存储数据方法内,自己定义一个key的规则进行数据存储

  • 我们存储都是通过PlayerPrefs来进行存储的
  • 保证key的唯一性我们就需要自己定一个key的规则
  • 我们自己定一个规则:keyName_数据类型_字段类型_字段名

存储数据方法内,遍历所有字段进行数据存储

//设置临时变量 方便遍历字段数组使用
string saveKeyName = "";
FieldInfo info;

//遍历字段数组
for (int i = 0; i < infos.Length; i++)
{
    //得到字段数组中每一个具体字段的信息
    //准备对每一个字段进行数据存储
    info = infos[i];

    //通过FieldInfo可以直接获取到 字段的类型 和字段的名字
    //字段的类型 info.FieldType.Name
    //字段的名字 info.Name;
    
    //要根据我们定的key的拼接规则 来进行唯一key的生成
    //Player1_PlayerInfo_Int32_age
    saveKeyName = keyName + "_" + dataType.Name +
        "_" + info.FieldType.Name + "_" + info.Name;
    
    //现在得到了唯一Key 按照我们的规则
    //接下来就要来通过PlayerPrefs来进行存储
    //如何获取值 info类的GetValue方法传入具体对象data
    //info.GetValue(data)
    
    //封装一个专门来存储值的方法 
    SaveValue(info.GetValue(data), saveKeyName);
}

创建存储具体值的方法,写存储一些常用类型变量的存储逻辑

/// <summary>
/// 存储具体值的方法
/// </summary>
/// <param name="value">值对象</param>
/// <param name="keyName">值对象唯一的key 按自定义规则生成的</param>
private void SaveValue(object value, string keyName)
{
    //直接通过PlayerPrefs来进行存储了
    //就是根据数据类型的不同 来决定使用哪一个API来进行存储
    //PlayerPrefs只支持3种类型存储 
    //判断 数据类型 是什么类型 然后调用具体的方法来存储

    //得到要存储的值对象的类型
    Type fieldType = value.GetType();

    //用多个if堆值对象的类型进行判断
    //是不是int
    if (fieldType == typeof(int))
    {
        Debug.Log("存储int" + keyName);
        PlayerPrefs.SetInt(keyName, (int)value);
    }
    //是不是float
    else if (fieldType == typeof(float))
    {
        Debug.Log("存储float" + keyName);
        PlayerPrefs.SetFloat(keyName, (float)value);
    }
    //是不是string
    else if (fieldType == typeof(string))
    {
        Debug.Log("存储string" + keyName);
        PlayerPrefs.SetString(keyName, value.ToString());
    }
    //是不是bool
    else if (fieldType == typeof(bool))
    {
        Debug.Log("存储bool" + keyName);
        //自己定义一个存储bool的规则
        PlayerPrefs.SetInt(keyName, (bool)value ? 1 : 0);
    }
}

创建测试类进行测试

public class PlayerInfo
{
    public int age = 10;
    public string name = "未命名";
    public float height = 177f;
    public bool sex = true;
}

public class Test : MonoBehaviour
{
    void Start()
    {
        PlayerInfo p = new PlayerInfo();
        //需要把这个数据对象的信息 存储到硬盘
        PlayerPrefsDataMgr.Instance.SaveData(p, "Player1");
    }
}

4.2 知识点代码

PlayerPrefsDataMgr

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

/// <summary>
/// PlayerPrefs数据管理类 统一管理数据的存储和读取
/// </summary>
public class PlayerPrefsDataMgr
{
    private static PlayerPrefsDataMgr instance = new PlayerPrefsDataMgr();

    public static PlayerPrefsDataMgr Instance
    {
        get
        {
            return instance;
        }
    }

    private PlayerPrefsDataMgr()
    {

    }


    /// <summary>
    /// 存储数据
    /// </summary>
    /// <param name="data">数据对象</param>
    /// <param name="keyName">数据对象的唯一key 自己控制</param>
    public void SaveData(object data, string keyName)
    {
        //就是要通过 Type 得到传入数据对象的所有的 字段
        //然后结合 PlayerPrefs来进行存储

        #region 第一步 获取传入数据对象的所有字段
        //获得传进来的data的Type
        Type dataType = data.GetType();
        //得到dataType的所有字段的数组
        FieldInfo[] infos = dataType.GetFields();
        #endregion

        #region 第二步 自己定义一个key的规则 进行数据存储
        //我们存储都是通过PlayerPrefs来进行存储的
        //保证key的唯一性 我们就需要自己定一个key的规则

        //我们自己定一个规则
        // keyName_数据类型_字段类型_字段名
        #endregion

        #region 第三步 遍历所有字段 进行数据存储

        //设置临时变量 方便遍历字段数组使用使用
        string saveKeyName = "";
        FieldInfo info;

        //遍历成字段数组
        for (int i = 0; i < infos.Length; i++)
        {
            //得到字段数组中每一个具体字段的信息
            //准备对每一个字段 进行数据存储
            info = infos[i];

            //通过FieldInfo可以直接获取到 字段的类型 和字段的名字
            //字段的类型 info.FieldType.Name
            //字段的名字 info.Name;

            //要根据我们定的key的拼接规则 来进行唯一key的生成
            //Player1_PlayerInfo_Int32_age
            saveKeyName = keyName + "_" + dataType.Name +
                "_" + info.FieldType.Name + "_" + info.Name;

            //现在得到了唯一Key 按照我们的规则
            //接下来就要来通过PlayerPrefs来进行存储
            //如何获取值 info类的GetValue方法传入具体对象data
            //info.GetValue(data)

            //封装一个专门来存储值的方法 
            SaveValue(info.GetValue(data), saveKeyName);
        }

        #endregion
    }

    /// <summary>
    /// 存储具体值的方法
    /// </summary>
    /// <param name="value">值对象</param>
    /// <param name="keyName">值对象唯一的key 按自定义规则生成的</param>
    private void SaveValue(object value, string keyName)
    {
        //直接通过PlayerPrefs来进行存储了
        //就是根据数据类型的不同 来决定使用哪一个API来进行存储
        //PlayerPrefs只支持3种类型存储 
        //判断 数据类型 是什么类型 然后调用具体的方法来存储

        //得到要存储的值对象的类型
        Type fieldType = value.GetType();

        //用多个if堆值对象的类型进行判断
        //是不是int
        if (fieldType == typeof(int))
        {
            Debug.Log("存储int" + keyName);
            PlayerPrefs.SetInt(keyName, (int)value);
        }
        //是不是float
        else if (fieldType == typeof(float))
        {
            Debug.Log("存储float" + keyName);
            PlayerPrefs.SetFloat(keyName, (float)value);
        }
        //是不是string
        else if (fieldType == typeof(string))
        {
            Debug.Log("存储string" + keyName);
            PlayerPrefs.SetString(keyName, value.ToString());
        }
        //是不是bool
        else if (fieldType == typeof(bool))
        {
            Debug.Log("存储bool" + keyName);
            //自己定义一个存储bool的规则
            PlayerPrefs.SetInt(keyName, (bool)value ? 1 : 0);
        }

    }

    /// <summary>
    /// 读取数据
    /// </summary>
    /// <param name="type">想要读取数据的 数据类型Type</param>
    /// <param name="keyName">数据对象的唯一key 自己控制</param>
    /// <returns></returns>
    public object LoadData(Type type, string keyName)
    {
        //不用object对象传入 而使用 Type传入
        //主要目的是节约一行代码(在外部)
        //假设现在你要 读取一个Player类型的数据 如果是object 你就必须在外部new一个对象传入
        //现在有Type的 你只用传入 一个Type typeof(Player) 然后我在内部动态创建一个对象给你返回出来
        //达到了 让你在外部 少写一行代码的作用

        //根据你传入的类型 和 keyName
        //依据你存储数据时  key的拼接规则 来进行数据的获取赋值 返回出去

        return null;
    }
}

Test

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class PlayerInfo
{
    public int age = 10;
    public string name = "未命名";
    public float height = 177f;
    public bool sex = true;
}

public class Test : MonoBehaviour
{
    void Start()
    {
        PlayerInfo p = new PlayerInfo();
        //需要把这个数据对象的信息 存储到硬盘
        PlayerPrefsDataMgr.Instance.SaveData(p, "Player1");
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏