C#模板生成
简要说明
创建代码有多种方式。最简单的,就按编辑器最初始的方法生成。稍微会点的就可以自己修改编辑器的模板。再深入一点的就可以自己定义一系列代码模板,保存到文本文件,再读出来,然后修改一些模板信息。用unity3d程序,我倒是习惯了在这程序中创建一个script而不是在vistual studio中去新建代码。这样的话,所有的代码类型,如Interface,struct,enum都需要在创建出一个”不正确“的类后修改,修改是个重复的过程,这个过程必须去掉。
而遗憾的是unity至今还是对所有的代码一视同仁,连图标都是用c#这么“经典”的一个图标。前一段时候,用过一些方法,无非是编写一个代码模板文档,创建时,调用这些模板。最大的缺陷是太复杂,在不同的项目或电脑上都要靠一些不想要的模板文件。
本文将使用Microsoft自己带的代码格式方案实现代码的生成(因为考虑到unity3d中暂不能很好的使用.net4.5,代码解析的模块还没有开发)。
成果展示
1.如果你喜欢简单一点,直接点右键快速创建不同的类
2.当然,也有基本的配制窗口
3.如果你需要创建一个不继承于其他类的数据模型类,你可以这样配制
4.以上这个配制后,点击create就可以生成代码模板到指定的文件夹了
5.以下是一个接口,创建效果。此外你已经熟悉代码规范了就可以在设置里面取消显示
技术要点
1.将c#代码单元生成字符串
代码也是一个个的文档,官方都有文档的格式,c#也不例外。这里只是按格式写,然后生成字符串,
需要说明的是c#并不能真的从string变成文档结构,至少官方貌似没有提供,但如果你可以使用net4.5以上的环境,
倒是可以研究下NRefactory
using (Microsoft.CSharp.CSharpCodeProvider cprovider = new Microsoft.CSharp.CSharpCodeProvider())
{
StringBuilder fileContent = new StringBuilder();
var option = new System.CodeDom.Compiler.CodeGeneratorOptions();
option.BlankLinesBetweenMembers = false;
using (StringWriter sw = new StringWriter(fileContent))
{
cprovider.GenerateCodeFromNamespace(nameSpace, sw, option);
}
return fileContent.ToString();
}
2.结合unity自己创建代码的方式
因为还没有找到,unity3d当前打开的文件夹路径,所以用了一个妥协的方案。就是先调用自带的方法创建一个脚本,
然后去修改里面的字符串(如果你找到了,不防提醒了一下)
internal static void QuickCreateTemplate<T>() where T : ScriptTemplate, new()
{
EditorApplication.ExecuteMenuItem("Assets/Create/C# Script");
EditorApplication.update = () =>
{
if (Selection.activeObject)
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var temp = new T();
temp.headerInfo.scriptName = Path.GetFileNameWithoutExtension(path);
var dir = Path.GetDirectoryName(path);
var scr = temp.CreateScript();
temp.SaveToFile(dir, scr);
EditorApplication.update = null;
}
};
}
3.窗体缓存
因为,将窗体的信息保存到本地文件,但又想要缓存一点信息,所以用了EditorPrefs和PlayerPrefs,
前面用来保存跨工程的用户信息和窗体信息,后面用来保存当前程序的信息。即使这样,因为要缓存模板抽象类的信息,
还用到了类型记录的一些方案
public static TempScriptWindow GetWindow()
{
var window = EditorWindow.GetWindow<TempScriptWindow>();
if (EditorPrefs.HasKey(prefer_key))
{
var json = EditorPrefs.GetString(prefer_window);
JsonUtility.FromJsonOverwrite(json, window);
window.LoadOldTemplates();
return window;
}
return window;
}
internal static ScriptTemplate LoadFromJson(ScriptTemplate old)
{
if (!string.IsNullOrEmpty(old.type) && old.GetType().FullName != old.type)
{
var type = Type.GetType(old.type);
if(type != null)
{
var temp = Activator.CreateInstance(type);
JsonUtility.FromJsonOverwrite(old.json, temp);
return temp as ScriptTemplate;
}
else
{
return old;
}
}
else
{
old.type = old.GetType().FullName;
return old;
}
}
4.unity3d自带列表ReorderableList以前没发现这个类,所以用了其他的插件来写列表。以上你看到的列表效果就是这样写的
protected void InitDetailList()
{
detailList = new ReorderableList(headerInfo.detailInfo, typeof(string), true, false, true, true);
detailList.onAddCallback += (x) => { headerInfo.detailInfo.Add(""); };
detailList.drawHeaderCallback = (x) => { EditorGUI.LabelField(x, "详细信息"); };
detailList.drawElementCallback += (x, y, z, w) => { headerInfo.detailInfo[y] = EditorGUI.TextField(x, headerInfo.detailInfo[y]); };
}
源码分享
为了方便拷贝使用,我直接在一个脚本中写了这些功能。虽然用了面对象的基本思路,但实际上在个文档中写,实在是难过,以后也尽量不要这样干。主要的是这个代码后面应该还会更新,如果喜欢,或者有建议可以到我github中去找:https://github.com/zouhunter/Editor_Extends/blob/master/Core/Editor/TempScriptWindow.cs
#region statement
/*************************************************************************************
* 作 者: zouhunter
* 时 间: 2018-02-02
* 详 细: 1.支持枚举、模型、结构和继承等类的模板。
2.支持快速创建通用型UI界面脚本
3.支持自定义模板类
4.自动生成作者、创建时间、描述等功能
5.支持工程同步(EditorPrefer)
*************************************************************************************/
#endregion
using System;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using UnityEditorInternal;
using System.CodeDom;
using System.IO;
using System.Text;
using NUnit.Framework.Constraints;
using NUnit.Framework;
namespace EditorTools
{
#region Window
/// <summary>
/// 一个创建脚本模板的窗口
/// </summary>
public class TempScriptWindow : EditorWindow
{
[MenuItem("Window/TempScriptWindow")]
static void Open()
{
var window = TempScriptHelper.GetWindow();
window.wantsMouseMove = true;
}
[SerializeField]
private List<ScriptTemplate> templates;
ScriptTemplate currentTemplates { get { if (templates != null && templates.Count > currentIndex) return templates[currentIndex]; return null; } }
private MonoScript script;
[SerializeField]
private bool isSetting;
[SerializeField]
private string authorName;
[SerializeField]
private string[] templateNames;
[SerializeField]
private int currentIndex;
private Vector2 scrollPos;
[SerializeField]
private string[] templateType;
private bool showRule;
private string codeRule;
private void OnEnable()
{
InitEnviroment();
}
private void OnDisable()
{
if (templates != null)
{
foreach (var item in templates)
{
item.SaveToJson();
}
}
EditorUtility.SetDirty(this);
TempScriptHelper.SaveWindow(this);
}
private void OnGUI()
{
DrawHead();
if (isSetting)
{
//绘制设置信息
DrawSettings();
}
else
{
if (templates == null)
{
Debug.Log("template == null");
templates = new List<ScriptTemplate>();
}
if (templates.Count == 0)
{
Debug.Log("AddTemplates");
AddTemplates();
}
currentIndex = GUILayout.Toolbar(currentIndex, templateNames);
using (var scroll = new EditorGUILayout.ScrollViewScope(scrollPos))
{
scrollPos = scroll.scrollPosition;
if (currentTemplates != null)
{
if (currentTemplates.GetType().FullName != currentTemplates.type)
{
templates[currentIndex] = TempScriptHelper.LoadFromJson(currentTemplates);
}
currentTemplates.OnBodyGUI();
if (currentTemplates.GetType().FullName == typeof(ScriptTemplate).FullName)
{
if (templateType.Length > currentIndex)
{
var type = Type.GetType(templateType[currentIndex]);
if(type != null)
{
templates[currentIndex] = Activator.CreateInstance(type) as ScriptTemplate;
Debug.Log("create new:" + currentTemplates.GetType());
}
else
{
Debug.LogFormat("{0} missing: clear templates", currentTemplates.GetType().FullName);
templates.Clear();
}
}
else
{
Debug.Log("unknow err: clear templates");
templates.Clear();
}
}
}
else
{
templates.Clear();
Debug.Log("templates.Count <= currentIndex");
}
}
if (currentTemplates != null)
{
currentTemplates.OnFootGUI();
}
}
}
private void InitEnviroment()
{
if (script == null) script = MonoScript.FromScriptableObject(this);
showRule = TempScriptHelper.GetRuleShowState();
if (string.IsNullOrEmpty(codeRule)) codeRule = TempScriptHelper.GetCodeRule();
if (string.IsNullOrEmpty(authorName)) authorName = TempScriptHelper.GetAuthor();
if (string.IsNullOrEmpty(authorName))
{
isSetting = true;
}
}
private void AddTemplates()
{
var assemble = this.GetType().Assembly;
var allTypes = assemble.GetTypes();
foreach (var item in allTypes)
{
if (item.IsSubclassOf(typeof(ScriptTemplate)))
{
var template = Activator.CreateInstance(item);
templates.Add(template as ScriptTemplate);
}
}
foreach (var item in templates)
{
item.OnEnable();
}
templateNames = templates.ConvertAll<string>(x => x.Name).ToArray();
templateType = templates.ConvertAll<string>(x => x.GetType().FullName).ToArray();
}
public void LoadOldTemplates()
{
for (int i = 0; i < templates.Count; i++)
{
if (templates[i] == null)
{
templates = null;
return;
}
var newitem = TempScriptHelper.LoadFromJson(templates[i]);
if (newitem == null)
{
templates = null;
return;
}
templates[i] = newitem;
}
templateNames = templates.ConvertAll<string>(x => x.Name).ToArray();
templateType = templates.ConvertAll<string>(x => x.GetType().FullName).ToArray();
}
private void DrawHead()
{
using (var hor = new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.ObjectField(script, typeof(MonoScript), false);
if (!isSetting && GUILayout.Button("setting", EditorStyles.miniButtonRight, GUILayout.Width(60)))
{
isSetting = true;
}
else if (isSetting && GUILayout.Button("confer", EditorStyles.miniButtonRight, GUILayout.Width(60)) && !string.IsNullOrEmpty(authorName))
{
isSetting = false;
}
}
if (!isSetting && GUILayout.Button("Clear", EditorStyles.toolbarButton))
{
if (currentTemplates != null)
currentTemplates.headerInfo = new TempScriptHeader() ;
templates.Clear();
}
}
private void DrawSettings()
{
using (var hor = new EditorGUILayout.HorizontalScope())
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.SelectableLabel("作者:", EditorStyles.miniLabel, GUILayout.Width(60));
authorName = EditorGUILayout.TextField(authorName);
if (EditorGUI.EndChangeCheck())
{
if (!string.IsNullOrEmpty(authorName))
{
TempScriptHelper.SaveAuthor(authorName);
}
}
}
EditorGUI.BeginChangeCheck();
showRule = EditorGUILayout.ToggleLeft("在生成的代码末尾显示规范:(熟悉后可关闭此功能)", showRule);
if (EditorGUI.EndChangeCheck())
{
TempScriptHelper.SetRuleShowState(showRule);
}
if (showRule)
{
using (var scrop = new EditorGUILayout.ScrollViewScope(scrollPos))
{
scrollPos = scrop.scrollPosition;
EditorGUILayout.TextArea(codeRule);
}
}
}
}
#endregion
#region Tools
/// <summary>
/// 任何脚本的头
/// </summary>
[System.Serializable]
public class TempScriptHeader
{
public string author;
public string time;
public string description;
public List<string> detailInfo = new List<string>();
public string scriptName;
public string nameSpace;
public void Update()
{
author = TempScriptHelper.GetAuthor();
time = System.DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
}
}
/// <summary>
/// 静态工具类
/// </summary>
public static class TempScriptHelper
{
private const string prefer_key = "temp_script_autor_name";
private const string prefer_window = "temp_script_window";
private const string code_rule_show = "temp_script_code_rule_show";
public static void SaveAuthor(string author)
{
EditorPrefs.SetString(prefer_key, author);
}
public static string GetAuthor()
{
return EditorPrefs.GetString(prefer_key);
}
public static void SaveWindow(TempScriptWindow window)
{
var json = JsonUtility.ToJson(window);
EditorPrefs.SetString(prefer_window, json);
}
public static TempScriptWindow GetWindow()
{
var window = EditorWindow.GetWindow<TempScriptWindow>();
if (EditorPrefs.HasKey(prefer_key))
{
var json = EditorPrefs.GetString(prefer_window);
JsonUtility.FromJsonOverwrite(json, window);
window.LoadOldTemplates();
return window;
}
return window;
}
internal static ScriptTemplate LoadFromJson(ScriptTemplate old)
{
if (!string.IsNullOrEmpty(old.type) && old.GetType().FullName != old.type)
{
var type = Type.GetType(old.type);
if(type != null)
{
var temp = Activator.CreateInstance(type);
JsonUtility.FromJsonOverwrite(old.json, temp);
return temp as ScriptTemplate;
}
else
{
return old;
}
}
else
{
old.type = old.GetType().FullName;
return old;
}
}
internal static void SetRuleShowState(bool enabled)
{
PlayerPrefs.SetInt(code_rule_show, enabled ? 1 : 0);
}
internal static bool GetRuleShowState()
{
if (PlayerPrefs.HasKey(code_rule_show))
{
return PlayerPrefs.GetInt(code_rule_show) == 1;
}
return true;
}
/*
1.私有字段:_field,m_field
2.公有字段:field
2.属性:Property
3.常量:CONST
4.静态变量:Field,Property
*/
internal static string GetCodeRule()
{
return @"#region 代码规范
/*************************************************************************************
【变量命名】:
1.私有字段:_field,m_field
2.公有字段:field
2.属性:Property
3.常量:CONST
4.静态变量:Field,Property
**************************************************************************************/
#endregion
";
}
internal static void QuickCreateTemplate<T>() where T : ScriptTemplate, new()
{
EditorApplication.ExecuteMenuItem("Assets/Create/C# Script");
EditorApplication.update = () =>
{
if (Selection.activeObject)
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var temp = new T();
temp.headerInfo.scriptName = Path.GetFileNameWithoutExtension(path);
var dir = Path.GetDirectoryName(path);
var scr = temp.CreateScript();
temp.SaveToFile(dir, scr);
EditorApplication.update = null;
}
};
}
}
#endregion
#region Templates
/// <summary>
/// 代码创建模板的模板
/// </summary>
[System.Serializable]
public class ScriptTemplate
{
[System.Serializable]
public class FieldItem
{
public string type;
public string elementName;
public string comment;
}
[System.Serializable]
public class PropertyItem
{
public string type;
public string elementName;
public string comment;
public bool get;
public bool set;
public PropertyItem()
{
get = set = true;
}
}
[SerializeField]
protected List<FieldItem> fields = new List<FieldItem>();
[SerializeField]
protected List<PropertyItem> propertys = new List<PropertyItem>();
public string json;
public string type;
public TempScriptHeader headerInfo = new TempScriptHeader();
public string path;
public virtual string Name { get { return null; } }
private ReorderableList detailList;
public virtual void OnBodyGUI() { }
public virtual void OnFootGUI()
{
if (detailList == null)
{
InitDetailList();
}
if (detailList.list != headerInfo.detailInfo)
{
detailList.list = headerInfo.detailInfo;
}
using (var horm = new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField("Namespace", GUILayout.Width(70));
headerInfo.nameSpace = EditorGUILayout.TextField(headerInfo.nameSpace, GUILayout.Width(60));
EditorGUILayout.LabelField("Type", GUILayout.Width(40));
headerInfo.scriptName = EditorGUILayout.TextField(headerInfo.scriptName, GUILayout.Width(60));
EditorGUILayout.LabelField("简介", GUILayout.Width(40));
headerInfo.description = EditorGUILayout.TextField(headerInfo.description);
if (GUILayout.Button("Load", EditorStyles.miniButtonRight, GUILayout.Width(60)))
{
OnLoadButtonClicked();
}
}
using (var hor = new EditorGUILayout.HorizontalScope())
{
using (var vertical = new EditorGUILayout.VerticalScope())
{
detailList.DoLayoutList();
}
using (var vertical = new EditorGUILayout.VerticalScope(GUILayout.Width(60)))
{
if (GUILayout.Button("Create", EditorStyles.miniButtonRight, GUILayout.Height(60)))
{
OnCreateButtonClicked();
}
}
}
}
public void OnEnable()
{
type = this.GetType().FullName;
Debug.Log(type);
}
public string CreateScript()
{
var ns = CreateNameSpace();
if (ns == null) return null;
var nsstr = ComplieNameSpaceToString(ns);
if (string.IsNullOrEmpty(nsstr)) return null;
var scriptStr = GetHeader() + nsstr + GetFooter();
if (string.IsNullOrEmpty(scriptStr))
{
EditorUtility.DisplayDialog("生成失败", "请看日志!", "确认");
return null;
}
return scriptStr;
}
public void SaveToJson()
{
json = null;
json = JsonUtility.ToJson(this);
if (string.IsNullOrEmpty(type))
{
type = this.GetType().FullName;
}
}
protected void InitDetailList()
{
detailList = new ReorderableList(headerInfo.detailInfo, typeof(string), true, false, true, true);
detailList.onAddCallback += (x) => { headerInfo.detailInfo.Add(""); };
detailList.drawHeaderCallback = (x) => { EditorGUI.LabelField(x, "详细信息"); };
detailList.drawElementCallback += (x, y, z, w) => { headerInfo.detailInfo[y] = EditorGUI.TextField(x, headerInfo.detailInfo[y]); };
}
protected void DrawFieldItem(Rect rect, FieldItem dataItem, bool haveType)
{
if (haveType)
{
var rect01 = new Rect(rect.x, rect.y, rect.width * 0.2f, EditorGUIUtility.singleLineHeight);
var typeRect = new Rect(rect.x + 0.2f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect02 = new Rect(rect.x + rect.width * 0.3f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
var commentRect = new Rect(rect.x + 0.6f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect03 = new Rect(rect.x + rect.width * 0.7f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
dataItem.elementName = EditorGUI.TextField(rect01, dataItem.elementName);
EditorGUI.LabelField(typeRect, "Type");
dataItem.type = EditorGUI.TextField(rect02, dataItem.type);
EditorGUI.LabelField(commentRect, "Comment");
dataItem.comment = EditorGUI.TextField(rect03, dataItem.comment);
}
else
{
var left = new Rect(rect.x, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
var right = new Rect(rect.x + rect.width * 0.4f, rect.y, rect.width * 0.6f, EditorGUIUtility.singleLineHeight);
var center = new Rect(rect.x + rect.width * 0.3f, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
dataItem.elementName = EditorGUI.TextField(left, dataItem.elementName);
EditorGUI.LabelField(center, "Comment");
dataItem.comment = EditorGUI.TextField(right, dataItem.comment);
}
}
protected void DrawPropertyItem(Rect rect, PropertyItem propertyItem)
{
var rect01 = new Rect(rect.x, rect.y, rect.width * 0.2f, EditorGUIUtility.singleLineHeight);
var typeRect = new Rect(rect.x + 0.2f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect02 = new Rect(rect.x + rect.width * 0.3f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
var commentRect = new Rect(rect.x + 0.6f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect03 = new Rect(rect.x + rect.width * 0.7f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
propertyItem.elementName = EditorGUI.TextField(rect01, propertyItem.elementName);
EditorGUI.LabelField(typeRect, "Type");
propertyItem.type = EditorGUI.TextField(rect02, propertyItem.type);
EditorGUI.LabelField(commentRect, "Comment");
propertyItem.comment = EditorGUI.TextField(rect03, propertyItem.comment);
var getLabelRect = new Rect(rect.x, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var getRect = new Rect(rect.x + 0.1f * rect.width, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var setLabelRect = new Rect(rect.x + 0.2f * rect.width, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var setRect = new Rect(rect.x + 0.3f * rect.width, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(getLabelRect, "get");
propertyItem.get = EditorGUI.Toggle(getRect, propertyItem.get);
EditorGUI.LabelField(setLabelRect, "set");
propertyItem.set = EditorGUI.Toggle(setRect, propertyItem.set);
}
protected virtual CodeNamespace CreateNameSpace()
{
return null;
}
protected string GetHeader()
{
headerInfo.Update();
var str1 = "#region statement\r\n" +
"/************************************************************************************* \r\n" +
" * 作 者: {0}\r\n" +
" * 时 间: {1}\r\n" +
" * 说 明: ";
var str2 = "\r\n ";
var str3 = "\r\n* ************************************************************************************/" +
"\r\n#endregion\r\n";
var headerStr = string.Format(str1, headerInfo.author, headerInfo.time);
for (int i = 0; i < headerInfo.detailInfo.Count; i++)
{
if (i == 0)
{
headerStr += string.Format("{0}.{1}", i + 1, headerInfo.detailInfo[i]);
}
else
{
headerStr += string.Format("{0}{1}.{2}", str2, i + 1, headerInfo.detailInfo[i]);
}
}
headerStr += str3;
return headerStr;
}
protected string ComplieNameSpaceToString(CodeNamespace nameSpace)
{
using (Microsoft.CSharp.CSharpCodeProvider cprovider = new Microsoft.CSharp.CSharpCodeProvider())
{
StringBuilder fileContent = new StringBuilder();
var option = new System.CodeDom.Compiler.CodeGeneratorOptions();
option.BlankLinesBetweenMembers = false;
using (StringWriter sw = new StringWriter(fileContent))
{
cprovider.GenerateCodeFromNamespace(nameSpace, sw, option);
}
return fileContent.ToString();
}
}
protected string GetFooter()
{
if (TempScriptHelper.GetRuleShowState())
{
var rule = TempScriptHelper.GetCodeRule();
return rule;
}
return null;
}
/// <summary>
/// 点击创建
/// </summary>
private void OnCreateButtonClicked()
{
if (string.IsNullOrEmpty(headerInfo.scriptName))
{
EditorUtility.DisplayDialog("脚本名为空", "请填写代码名称!", "确认");
return;
}
if (string.IsNullOrEmpty(path))
{
if (ProjectWindowUtil.IsFolder(Selection.activeInstanceID))
{
path = AssetDatabase.GetAssetPath(Selection.activeInstanceID);
}
else if (Selection.activeObject != null)
{
var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);
if (!string.IsNullOrEmpty(assetPath))
{
path = assetPath.Replace(System.IO.Path.GetFileName(assetPath), "");
}
}
}
var scriptStr = CreateScript();
if (!string.IsNullOrEmpty(scriptStr))
{
SaveToFile(path, scriptStr);
}
}
/// <summary>
/// 保存到文件
/// </summary>
/// <param name="path"></param>
/// <param name="scriptStr"></param>
public void SaveToFile(string path, string scriptStr)
{
if (!string.IsNullOrEmpty(path))
{
var scriptPath = string.Format("{0}/{1}.cs", path, headerInfo.scriptName);
System.IO.File.WriteAllText(scriptPath, scriptStr, System.Text.Encoding.UTF8);
AssetDatabase.Refresh();
}
else
{
EditorUtility.DisplayDialog("路径不明", "请选中文件夹后重试", "确认");
}
}
/// <summary>
/// 点击加载代码
/// </summary>
private void OnLoadButtonClicked()
{
if (!(Selection.activeObject is TextAsset))
{
EditorUtility.DisplayDialog("未选中", "请选中需要解析的代码后继续", "确认");
return;
}
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
if (!path.EndsWith(".cs"))
{
EditorUtility.DisplayDialog("未选中", "请选中需要解析的代码后继续", "确认");
return;
}
using (var provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("CSharp"))
{
EditorUtility.DisplayDialog("未开发", ".net 3.5暂无该实现", "确认");
var fileContent = System.IO.File.ReadAllText(path, Encoding.UTF8);
using (StringReader sr = new StringReader(fileContent))
{
var nameSpaceUnit = provider.Parse(sr);
Debug.Log(nameSpaceUnit);
}
}
}
}
#endregion
#region Enum
/// <summary>
/// 1.枚举类型脚本
/// </summary>
[Serializable]
public class EnumScriptTemplate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Enum", priority = 5)]
static void CreateEnum()
{
TempScriptHelper.QuickCreateTemplate<EnumScriptTemplate>();
}
public override string Name
{
get
{
return "Enum";
}
}
private ReorderableList reorderableList;
public EnumScriptTemplate()
{
reorderableList = new ReorderableList(fields, typeof(string));
reorderableList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "枚举列表"); };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], false);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> fields = new List<CodeMemberField>();
foreach (var item in base.fields)
{
CodeMemberField prop = new CodeMemberField();
prop.Name = item.elementName;
prop.Comments.Add(new CodeCommentStatement(item.comment));
fields.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.IsEnum = true;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(headerInfo.description, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var field in fields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
return nameSpace;
}
public override void OnBodyGUI()
{
reorderableList.DoLayoutList();
}
}
#endregion
#region DataModel
/// <summary>
/// 2.数据模拟类
/// </summary>
[Serializable]
public class DataModelTemplate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Model", priority = 5)]
static void CreateModel()
{
TempScriptHelper.QuickCreateTemplate<DataModelTemplate>();
}
public override string Name
{
get
{
return "Model";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine",
"UnityEngine.UI",
"System.Collections",
"System.Collections.Generic",
};
private ReorderableList nameSpaceList;
private ReorderableList reorderableList;
public DataModelTemplate()
{
reorderableList = new ReorderableList(fields, typeof(string));
reorderableList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "模型名"); };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], true);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空间"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> fields = new List<CodeMemberField>();
foreach (var item in base.fields)
{
CodeMemberField prop = new CodeMemberField();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public;
prop.Name = item.elementName;
prop.Comments.Add(new CodeCommentStatement(item.comment));
fields.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(System.SerializableAttribute).FullName));
wrapProxyClass.IsClass = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "数据模型" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var field in fields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
reorderableList.DoLayoutList();
}
}
#endregion
#region Static
/// <summary>
/// 3.静态类
/// </summary>
[Serializable]
public class StaticClassTemplate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Static", priority = 5)]
static void CreateModel()
{
TempScriptHelper.QuickCreateTemplate<StaticClassTemplate>();
}
public override string Name
{
get
{
return "Static";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine"
};
private ReorderableList nameSpaceList;
private ReorderableList propertyList;
private ReorderableList fieldList;
public StaticClassTemplate()
{
fieldList = new ReorderableList(fields, typeof(string));
fieldList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
fieldList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "字段"); };
fieldList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], true);
};
propertyList = new ReorderableList(propertys, typeof(string));
propertyList.onAddCallback += (x) => { propertys.Add(new PropertyItem()); };
propertyList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "属性"); };
propertyList.elementHeightCallback = (x) => { return 2 * EditorGUIUtility.singleLineHeight; };
propertyList.drawElementCallback += (x, y, z, w) =>
{
DrawPropertyItem(x, propertys[y]);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空间"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> codeFields = new List<CodeMemberField>();
foreach (var item in fields)
{
CodeMemberField field = new CodeMemberField();
field.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
field.Attributes = MemberAttributes.Public | MemberAttributes.Static;
field.Name = item.elementName;
//field.InitExpression = invokeExpression;
field.Comments.Add(new CodeCommentStatement(item.comment));
codeFields.Add(field);
}
List<CodeMemberProperty> propertysMemper = new List<CodeMemberProperty>();
foreach (var item in propertys)
{
CodeMemberProperty prop = new CodeMemberProperty();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public|MemberAttributes.Static;
prop.Name = item.elementName;
prop.HasGet = item.get;
prop.HasSet = item.set;
//CodeExpression invokeExpression = new CodePropertyReferenceExpression();
prop.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
prop.Comments.Add(new CodeCommentStatement(item.comment));
propertysMemper.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;//没有静态?
wrapProxyClass.Attributes = MemberAttributes.Static;
wrapProxyClass.IsClass = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "静态类" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var prop in propertysMemper)
{
wrapProxyClass.Members.Add(prop);
}
foreach (var field in codeFields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
fieldList.DoLayoutList();
propertyList.DoLayoutList();
}
}
#endregion
#region Struct
/// <summary>
/// 5.结构体模板
/// </summary>
[Serializable]
public class StructTempate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Struct", priority = 5)]
static void CreateStruct()
{
TempScriptHelper.QuickCreateTemplate<StructTempate>();
}
public override string Name
{
get
{
return "Struct";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine",
"UnityEngine.UI",
"System.Collections",
"System.Collections.Generic",
};
private ReorderableList nameSpaceList;
private ReorderableList reorderableList;
public StructTempate()
{
reorderableList = new ReorderableList(fields, typeof(string));
reorderableList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "模型名"); };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], true);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空间"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> fields = new List<CodeMemberField>();
foreach (var item in base.fields)
{
CodeMemberField prop = new CodeMemberField();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public;
prop.Name = item.elementName;
prop.Comments.Add(new CodeCommentStatement(item.comment));
fields.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.IsStruct = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "结构体" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var field in fields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
reorderableList.DoLayoutList();
}
}
#endregion
#region Interface
/// <summary>
/// 6.接口创建模板
/// </summary>
[Serializable]
public class InterfaceTempate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Interface", priority = 5)]
static void CreateEnum()
{
TempScriptHelper.QuickCreateTemplate<InterfaceTempate>();
}
public override string Name
{
get
{
return "Interface";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine"
};
private ReorderableList nameSpaceList;
private ReorderableList reorderableList;
public InterfaceTempate()
{
reorderableList = new ReorderableList(propertys, typeof(string));
reorderableList.onAddCallback += (x) => { propertys.Add(new PropertyItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "属性"); };
reorderableList.elementHeightCallback = (x) => { return 2 * EditorGUIUtility.singleLineHeight; };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawPropertyItem(x, propertys[y]);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空间"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberProperty> propertysMemper = new List<CodeMemberProperty>();
foreach (var item in propertys)
{
CodeMemberProperty prop = new CodeMemberProperty();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public;
prop.Name = item.elementName;
prop.HasGet = item.get;
prop.HasSet = item.set;
prop.Comments.Add(new CodeCommentStatement(item.comment));
propertysMemper.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.IsInterface = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "接口" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var prop in propertysMemper)
{
wrapProxyClass.Members.Add(prop);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
reorderableList.DoLayoutList();
}
}
#endregion
///下面可以自定义你的代码生成模板
///...
/// <summary>
/// UI模板
/// </summary>
//[Serializable]
//public class UIPanelTempate : ScriptTemplate
//{
// public override string Name
// {
// get
// {
// return "UIPanel";
// }
// }
// protected override CodeNamespace CreateNameSpace()
// {
// return null;
// }
// public override void OnBodyGUI()
// {
// }
//}
}
上一篇: 由同源策略到前端跨域
下一篇: 方法的定义及调用