基于Json(键值对)配置文件的配置管理器
前言:在这个专题中,我们会讲解UI框架项目。首先我们先来编写基于键值对的的通用的配置管理器。在UI框架的项目中,我们会把我们一个一个的窗体都存为预设放在Resources目录下。使用Resources.Load进行加载存储在集合中。
一:Json文件的解析的Demo
在讲解配置管理器之前,我们先来说一下Json的解析,我们在这里使用Unity官方中的JsonUtility。
在官方的API中主要是这三个方法的使用,我们会一一的进行讲解。首先我们先给出一个Json配置文件。
大家如果对Json了解的话,就会知道Json的格式:1.数据保存在键值对中,用逗号做分割。2.大括号保存对象,中括号保存数组。在上面我们看到,我们People对象中有我们需要的数据,存储名称和年龄信息,但是在People中有一个数组,说明这个对象中许多数据,数据都保存在键值对中,用逗号做分割来存储一个又一个的数据。我们在这里一个类,来声明一组信息,这个类需要被序列化【Serializable】,在这里需要注意的是,我们在People类声明的Name和Age必须跟配置文件中的Name和Age相同。
namespace TestJson { [Serializable] public class People { #region 字段和属性定义 public string Name; //名称 public int Age; //年龄 #endregion #region 公共方法的定义 #endregion #region 私有方法的定义 #endregion }//class_end }
我们在需要声明存放People类的多条数据,我们声明一个集合(集合的字段People必须跟配置文件中的People相同):
namespace DemoProject { [Serializable] public class PersonInfo { #region 字段和属性定义 public List<People> People = new List<People>(); #endregion #region 公共方法的定义 #endregion #region 私有方法的定义 #endregion }//class_end }
接下来需要对Resources目录下的Json文件进行解析。
namespace DemoProject { public class TestUnityJsonTwo : MonoBehaviour { #region 字段和属性定义 #endregion void Start() { //提取文件 得到字符串数据 TextAsset textAsset = Resources.Load<TextAsset>("Json\People"); //进行反序列化工作(文件-------->对象) PersonInfo personInfo = JsonUtility.FromJson<PersonInfo>(textAsset.text); //显示对象数据 foreach (People people in personInfo.People) { print(string.Format("Name:{0},Age:{1}", people.Name, people.Age)); } } #region 公共方法的定义 #endregion #region 私有方法的定义 #endregion }//class_end }
得到结果:
二:Json解析在具体的项目中的应用
首先先看一下我们在Project面板下的UI窗体预设的路径。
我们会在Json配置文件中以键值对的形式把数据全部的保存下来。键:UI窗体的名称,值:UI窗体的路径信息。如下所示:
这样做的目的是什么,主要是为了我们方便的管理。便于我们以后的维护。当我们开发完通用的配置管理器之后,当我们在以后的项目中在次遇到基于键值对Json文件时,就可以拿来使用了。
首先我们先来开发配置管理器接口。功能:基于“键值对”配置文件的通用的解析。我们在接口中声明集合中的指定属性和得到配置文件的最大的数量。
interface IConfigManagerAble { Dictionary<string, string> AppSetting { get; } //得到键值对集合数据 int GetAppSettingMaxNumber(); //得到配置文件的最大的数量 }//class_end
我们还需要定义键值节点,这个类需要进行反序列化,如下所示:
[Serializable] internal class KeyValueNode { public string Key = null; //键 public string Value = null; //值 }
我们还需要定义键值集合用来存储所有的键值对的数据,我们可以使用List<KeyValueNode>集合类来进行存储。
[Serializable] internal class KeyValueInfo { public List<KeyValueNode> ConfigInfo = new List<KeyValueNode>(); }
配置管理器接口全部的代码实现如下:
namespace UIFromWork { interface IConfigManagerAble { Dictionary<string, string> AppSetting { get; } //得到键值对集合数据 int GetAppSettingMaxNumber(); //得到配置文件的最大的数量 }//class_end [Serializable] internal class KeyValueInfo { public List<KeyValueNode> ConfigInfo = new List<KeyValueNode>(); } [Serializable] internal class KeyValueNode { public string Key = null; //键 public string Value = null; //值 } }
这时候需要定义接口的实现类,我们定义ConfigManagerByJson类继承接口。我们在上面说到,我们需要把数据与键值对的形式存储到集合中,我们很容易想到使用使用字段集合,因为接口中定义了集合的属性为只属性,我们也需要实现它:
#region 字段和属性定义 /*** * 保存"键值对"应用集合设置集合 * */ private readonly Dictionary<string, string> _appSetting = new Dictionary<string, string>(); /*** * 只读属性 * */ public Dictionary<string, string> AppSetting { get { return _appSetting; } } #endregion
我们在构造函数中进行初始化解析Json数据加载到集合中。我们需要json数据的路径。所有参数是:UI窗体预设的路径。我们先来写一个私有的方法来进行初始化解析:
/// <summary> /// 初始化解析Json数据加载到集合中 /// </summary> /// <param name="jsonPath">Json数据路径</param> private void InitAndAnalysisJson(string jsonPath) { KeyValueInfo keyValueInfo = null; //参数的检查 if (string.IsNullOrEmpty(jsonPath)) return; //解析Json配置文件 try { //得到文件流数据 TextAsset textAsset = Resources.Load<TextAsset>(jsonPath); //进行反序列化(数据------>对象) keyValueInfo = JsonUtility.FromJson<KeyValueInfo>(textAsset.text); } catch { //抛自定义异常 throw new JsonAnlysisException(string.Format("{0}/InitAndAnalysisJson()/Json Analysis Exception !! Parameter : {1}", GetType(), jsonPath)); } //数据加载到集合中 foreach (KeyValueNode node in keyValueInfo.ConfigInfo) { _appSetting.Add(node.Key, node.Value); } }
这时候在构造函数中写入方法即可:
public ConfigManagerByJson(string jsonPath) { //初始化解析Json数据加载到集合中 InitAndAnalysisJson(jsonPath); }
全部的实现代码如下:
namespace UIFromWork { public class ConfigManagerByJson : IConfigManagerAble { #region 字段和属性定义 /*** * 保存"键值对"应用集合设置集合 * */ private readonly Dictionary<string, string> _appSetting = new Dictionary<string, string>(); /*** * 只读属性 * */ public Dictionary<string, string> AppSetting { get { return _appSetting; } } #endregion #region 构造函数的定义 public ConfigManagerByJson(string jsonPath) { //初始化解析Json数据加载到集合中 InitAndAnalysisJson(jsonPath); } #endregion #region 公共方法的定义 /// <summary> /// 得到集合中的最大的数量 /// </summary> /// <returns></returns> public int GetAppSettingMaxNumber() { if (_appSetting != null && _appSetting.Count >= 1) { return _appSetting.Count; } else { return 0; } } #endregion #region 私有方法的定义 /// <summary> /// 初始化解析Json数据加载到集合中 /// </summary> /// <param name="jsonPath">Json数据路径</param> private void InitAndAnalysisJson(string jsonPath) { KeyValueInfo keyValueInfo = null; //参数的检查 if (string.IsNullOrEmpty(jsonPath)) return; //解析Json配置文件 try { //得到文件流数据 TextAsset textAsset = Resources.Load<TextAsset>(jsonPath); //进行反序列化(数据------>对象) keyValueInfo = JsonUtility.FromJson<KeyValueInfo>(textAsset.text); } catch { //抛自定义异常 throw new JsonAnlysisException(string.Format("{0}/InitAndAnalysisJson()/Json Analysis Exception !! Parameter : {1}", GetType(), jsonPath)); } //数据加载到集合中 foreach (KeyValueNode node in keyValueInfo.ConfigInfo) { _appSetting.Add(node.Key, node.Value); } } #endregion }//class_end }
这时候我们就可以在客户端进行调用了,我们先声明一个集合:
private Dictionary<string, string> _dicFormPaths = new Dictionary<string, string>(); //UI窗体预设的路径(1.窗体预设名称 2.窗体预设路径)
我们把路径数据全部存储到集合中,这时候可以使用文件配置管理器的脚本,代码如下:
/// <summary> /// 初始化"UI窗体预设"路径数据 /// </summary> private void InitUiFormPathData() { IConfigManagerAble configManager = new ConfigManagerByJson(“路径信息”); if (configManager != null) { _dicFormPaths = configManager.AppSetting; } }