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()
    //    {

    //    }
    //}

}



  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值