上一篇介绍了自定义编辑器窗口,这一篇来介绍配置类文件的生成。话不多说直接开始吧。
在项目配置时我们经常会使用Excel来作为配表工具,所以本文的配表生成类文件都是针对Excel的。
上图是一张配表的示例,左下角的页签名称用来定义生成类文件的类名,在左上角则是定义的数据结构和数据值。第一行用于描述,生成类文件后用于备注。第二行为类型,生成类文件后为成员变量的类型。第三行为字段名,生成类文件后为成员变量的变量名。第四行以下为数据部分,生成类文件暂时用不到。
上面对Excel配表的解析规则是自行制定的,这里的解析规则只是根据我自己的项目需求制定的,在理解了解析方式之后可以自己制定解析规则,类文件也可以根据自己的需求来生成。
下面我们赶紧来看看如何解析生成配置文件,配置类文件的生成主要分为三个部分:
- 配置文件的读取与解析
- 类脚本内容的生成
- 类脚本的导出
配置的读取和解析需要用到第三方插件ExcelDataReader,官网链接在本文的最后,需要的小伙伴可以自行前往下载。
using System.IO;
using System.Text;
using UnityEngine;
using Excel;
public class ConfigScriptGenerator
{
private string className;
private string[] descriptionArray;
private string[] typeArray;
private string[] fieldArray;
private StringBuilder stringBuilder = new StringBuilder();
/// <summary>生成脚本</summary>
/// <param name="configPath">配置路径</param>
/// <param name="exportPath">输出路径</param>
public void GenerateScript(string configPath, string exportPath)
{
if(File.Exists(configPath))
{
ParseConfig(configPath);
GenerateCode();
ExportFile(exportPath);
}
else
{
Debug.Log(string.Format("Generate config error, Config is not exist. config path is {0}.", configPath));
}
}
/// <summary>解析配置</summary>
/// <param name="configPath">配置路径</param>
private void ParseConfig(string configPath)
{
FileStream stream = File.OpenRead(configPath);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
className = excelReader.Name;
while(excelReader.Read())
{
if(excelReader.Depth == (int)EnumConfigFormat.Description)
{
descriptionArray= GetDatas(excelReader);
}
else if(excelReader.Depth == (int)EnumConfigFormat.Type)
{
typeArray= GetDatas(excelReader);
}
else if(excelReader.Depth == (int)EnumConfigFormat.Field)
{
fieldArray= GetDatas(excelReader);
}
else
{
break;
}
}
excelReader.Close();
}
/// <summary>获取数据</summary>
/// <param name="excelReader">excelReader</param>
/// <returns></returns>
private string[] GetDatas(IExcelDataReader excelReader)
{
string[] datas = new string[excelReader.FieldCount];
for(int i = 0; i < excelReader.FieldCount; i++)
{
datas[i] = excelReader.GetString(i);
}
return datas;
}
}
首先是读取和解析的部分,通过系统方法File.OpenRead获取到FileStream变量,将变量传给ExcelReaderFactory.CreateOpenXmlReader来创建IExcelDataReader对象用于读取Excel数据。然后通过循环调用excelReader.Read的方式,逐行获取Excel中的数据。获取每一行的数据后再次进行遍历,获取每一个单元格内的数据,并生成数组数据。这里通过两次循环的方式获取到Excel中每个单元格中的数据,如何使用这些数据小伙伴可以自行发挥。
/// <summary>生成代码</summary>
private void GenerateCode()
{
stringBuilder.Append("/*Auto-create script.\n");
stringBuilder.Append(" * Don't Edit it. */\n");
stringBuilder.Append("\n");
stringBuilder.Append("using System.Collections.Generic;\n");
stringBuilder.Append("\n");
stringBuilder.Append("namespace Framework.Config\n");
stringBuilder.Append("{\n");
stringBuilder.AppendFormat("\tpublic class {0}\n", className);
stringBuilder.Append("\t{\n");
for(int i = 0; i < descriptionArray.Length; i++)
{
stringBuilder.AppendFormat("\t\t/// <summary>{0}</summary>\n", descriptionArray[i]);
if(i == 0)
stringBuilder.Append("\t\tpublic object id;\n");
else
stringBuilder.AppendFormat("\t\tpublic {0} {1};\n", typeArray[i], fieldArray[i]);
}
stringBuilder.Append("\t}\n");
stringBuilder.Append("}");
}
获取到配表中的数据之后,就是生成代码了。因为需要频繁进行字符串操作,所以这里使用StringBuilder来操作字符串。通过操作字符串来生成C#文件中的代码。
/// <summary>输出文件</summary>
/// <param name="exportPath">输出路径</param>
private void ExportFile(string exportPath)
{
string path = string.Format("{0}/{1}.cs", exportPath, className);
string content = stringBuilder.ToString();
File.WriteAllText(path, content);
Debug.Log(string.Format("Config generate class-file complete. File name is {0}.cs", className));
}
生成代码之后最后一步就是将代码导出成 .cs 文件,这样配置的类文件就算是生成好了。在项目中使用的时候就可以将Json文件反序列化成对应的类型。
相关链接
ExcelDataReader官网 https://archive.codeplex.com/?p=exceldatareader