为了庆祝关注量+1 所以出来更新一篇
【此篇针对于UNITY】
最近在自己搭破架子 碰到一个问题:
我的Panel类是要在运行时 全部预先创建实例 这就有个很闹心的问题 我加一个新的 就要去预读取类中加上这个类的代码
emmmmm 很闹心 所以就做了工作来生成代码
开始吧~
简单一点 先创建三个类【本来是应该继承自基类的 为了方便 就不继承了】
public class Panel1 : MonoBehaviour {
public Panel1()
{
Debug.LogFormat("当前文件 Panel1");
}
}
public class Panel2 : MonoBehaviour {
public Panel2()
{
Debug.LogFormat("当前文件 Panel2");
}
}
public class Panel3 : MonoBehaviour {
public Panel3()
{
Debug.LogFormat("当前文件 Panel3");
}
}
然后再来一个预读的类
public class PanelManager {
public PanelManager()
{
Panel1 panel1 = new Panel1();
Panel2 panel2 = new Panel2();
Panel3 panel3 = new Panel3();
}
}
看到了吧 每次有新的类 都要手动加进来
所以在工具栏中 加一个按钮吧
先看一下目录结构
PanelManager是运行时预读的类
Panel1 Panel2 Panel3是要预读的类
GenerateFileMenu是工具栏扩展的类
首先来改造一下PanelManager 添加一个标识符 用来标识要修改的地方
public class PanelManager {
public PanelManager()
{
//#@#@# 生成开始标识符
Panel1 panel1 = new Panel1();
Panel2 panel2 = new Panel2();
Panel3 panel3 = new Panel3();
//@#@#@ 生成结束标识符
}
}
接下来看一下这个工具栏扩展类做了啥
//生成菜单
public class GenerateFileMenu {
[MenuItem("文件生成/生成Panel预读取数据 %#_g", false, 100)]
private static void GeneratePrePanelLoadData()
{
Debug.Log("生成数据");
//加载程序集 ①
Assembly assem = Assembly.Load("Assembly-CSharp");
//存储读出的内容
List<string> fileStrList = new List<string>();
//读取预加载管理文件 ②
string filePath = @"Assets/Script/PanelManager.cs";
StreamReader readFileStream = new StreamReader(filePath);
while (!readFileStream.EndOfStream)
{
string fileLine = readFileStream.ReadLine();
fileStrList.Add(fileLine);
}
//③
readFileStream.Close();
//重新写入文件 ④
StreamWriter writeFileStream = new StreamWriter(filePath, false, Encoding.UTF8);
bool isInserting = false;
foreach (string fileStr in fileStrList)
{
if (true == isInserting)
{
//是否开始插入 ⑤
if (true == fileStr.Contains("@#@#@"))
{
writeFileStream.WriteLine(fileStr);
isInserting = false;
}
}
else
{
writeFileStream.WriteLine(fileStr);
//是否开始插入
if (true == fileStr.Contains("#@#@#"))
{
isInserting = true;
//获取全部Panel文件名 ⑥
string panelPath = "Assets/Script/PanelScript";
List<string> nameStrList = GetFilesInEachLayerDirectory(panelPath, "*.cs");
foreach (string nameAllStr in nameStrList)
{
//⑦
string nameStr = nameAllStr.Split('.')[0];
//⑧
Type clsType = assem.GetType(nameStr);
if (null == clsType)
{
Debug.LogFormat("程序集中找不到{0}这个类", nameStr);
}
else
{
//⑨
string fUpperValue = nameStr.Substring(0, 1).ToUpper() + nameStr.Substring(1);
string fLowerValue = nameStr.Substring(0, 1).ToLower() + nameStr.Substring(1);
writeFileStream.WriteLine(string.Format("\t\t{0} {1} = new {2}();", fUpperValue, fLowerValue, fUpperValue));
}
}
}
}
}
writeFileStream.Close();
}
//获取目录和子目录下所有文件
private static List<string> GetFilesInEachLayerDirectory(string path, string extension = "*")
{
//文件名列表
List<string> nameStrList = new List<string>();
//获取目录下数据
DirectoryInfo root = new DirectoryInfo(path);
//读取所有文件
foreach (FileInfo file in root.GetFiles(extension))
{
nameStrList.Add(file.Name);
}
//子目录查找
foreach (DirectoryInfo folder in root.GetDirectories())
{
string folderPath = path + "/" + folder.Name;
List<string> deepNameStrList = GetFilesInEachLayerDirectory(folderPath, extension);
foreach (string nameStr in deepNameStrList)
{
nameStrList.Add(nameStr);
}
}
return nameStrList;
}
}
①因为Editor和功能不是一个DLL 所以这里要先加载程序集 可以在你的项目中看一下叫什么
②这里的路径用了@ 是为了让字符串不做转译
可以看这里 https://blog.youkuaiyun.com/Czhenya/article/details/97895301
③记得读取完数据 要关上啊 不然后面写入的时候 就会报错的
④重新写入文件 用UTF-8 防止乱码
⑤这里用了Contains来匹配刚刚加进去的标识符
⑥GetFilesInEachLayerDirectory这个方法就是遍历目录下所有的cs文件
⑦这里获取到的是完整的文件名 所以分割一下 把文件后缀名去掉
⑧这里通过程序集来反射出类 【这里我试了很久 原来是要用加载的程序集才行 现在我终于懂了反射是怎么回事了】
这里倒是有个问题 文件名和类名要相同 所以我就给自己定个潜规则 文件名和类名要相同 【我暂时没有别的办法】
⑨这里就开始写入代码了 根据需要来写就好了
差不多就是这样 Ctrl+Shift+G 直接就生成好了 稳得一批