相关文章推荐
重感情的板凳  ·  scala ...·  4 天前    · 
淡定的蚂蚁  ·  numpy ...·  10 月前    · 

手写一个C#文件解析(命名空间+类名)

开发环境:VS2013+.Net2.0

Unity版本:5.3.7

XLua版本:v2.1.10

运行环境:Windows10


因为项目使用XLua做热更,需要在代码中指定哪些类可以打补丁,文档介绍:

## 标识要热更新的类型

和其它配置一样,有两种方式

方式一:直接在类里头打Hotfix标签;

方式二:在一个static类的static字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置,比如根据Namespace做白名单。

~~~csharp
public static class HotfixCfg
{
[Hotfix]
public static List<Type> by_field = new List<Type>()
{
typeof(HotFixSubClass),
typeof(GenericClass<>),
};

[Hotfix]
public static List<Type> by_property
{
get
{
return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
where type.Namespace == "XXXX"
select type).ToList();
}
}
}


想把项目中大多数自定义的类添加Hotfix标签,又不想一个类一个类去查找,前期如果划分好命名空间,也比较方便的打标签,但是这是半路接手的项目,没办法,所以想找个把代码文件转成代码结构的工具,而 把C#代码文件解析为CodeCompileUnit 这个的研究就是想解决这个问题,但是Unity不支持CodeCompileUnit,于是决定自己写一个解析,目前只需要命名空间+类名,所以解析也只做到这一步,其他如果有需要方法名什么的,再补充吧


Dome代码比较凌乱,直接用VS2013创建一个控制台程序就能跑,里面包括两种解析方式,结果都一样,一种是逐字符解析Parse1,一种是关键信息解析Parse2:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ConsoleApplication1
    class Program
        static void Main(string[] args)
            List<string> allFullClassNameList = new List<string>();
            string[] csFilePaths = Directory.GetFiles("Scripts", "*.cs", SearchOption.AllDirectories);
            for (int i = 0; i < csFilePaths.Length; i++)
                var csFilePath = csFilePaths[i];
                Console.WriteLine(string.Format("{0}/{1} {2}", i, csFilePaths.Length, csFilePath));
                string code = File.ReadAllText(csFilePath);
                CodeStructure cs = CodeStructureHelper.Parse2(code);
                //转成完整类名
                List<string> fullClassNameList = CodeStructureHelper.GetFullClassNameList(cs);
                allFullClassNameList.AddRange(fullClassNameList);
            File.WriteAllLines("allFullClassNames.txt", allFullClassNameList.ToArray());
    /// <summary>
    /// C#代码文档结构
    /// </summary>
    public class CodeStructureHelper
        /// <summary>
        /// 获得完整类名
        /// </summary>
        /// <param name="codeStructure"></param>
        /// <returns></returns>
        public static List<string> GetFullClassNameList(CodeStructure codeStructure)
            List<string> fullClassNameList = new List<string>();
            //命名空间
            foreach (var codeNamespace in codeStructure.CodeNamespaceList)
                GetFullClassNameList(ref fullClassNameList, "", codeNamespace);
            foreach (var codeClass in codeStructure.CodeClassList)
                StringBuilder parentName = new StringBuilder();
                GetFullClassNameList(ref fullClassNameList, "", codeClass);
            return fullClassNameList;
        public static void GetFullClassNameList(ref List<string> fullClassNameList, string parentName, CodeNamespace codeNamespace)
            if (codeNamespace.InternalCodeNamespaceList.Count > 0
                || codeNamespace.CodeClassesList.Count > 0)
                parentName = splicingParentName(parentName, codeNamespace.Name);
                //子命名空间
                foreach (var child in codeNamespace.InternalCodeNamespaceList)
                    GetFullClassNameList(ref fullClassNameList, parentName, child);
                //该命名空间下的类
                foreach (var child in codeNamespace.CodeClassesList)
                    GetFullClassNameList(ref fullClassNameList, parentName, child);
        public static void GetFullClassNameList(ref List<string> fullClassNameList, string parentName, CodeClass codeClass)
            string fullClassName = splicingParentName(parentName, codeClass.Name);
            fullClassNameList.Add(fullClassName);
            //内部类
            if (codeClass.InternalCodeClassList.Count > 0)
                foreach (var child in codeClass.InternalCodeClassList)
                    GetFullClassNameList(ref fullClassNameList, fullClassName, child);
        //拼接父节点名字
        private static string splicingParentName(string parentName, string name)
            if (string.IsNullOrEmpty(parentName))
                return name;
            return string.Format("{0}.{1}", parentName, name);
        #region 域判断文字
        /// <summary>
        /// 右斜杠
        /// </summary>
        public const char RightSlashStr = '\\';
        /// <summary>
        /// 双斜杠注释
        /// </summary>
        public const string CommentsStr = "//";
        /// <summary>
        /// 星号注释开始
        /// </summary>
        public const string BeginStarCommentsStr = "/*";
        /// <summary>
        /// 星号注释结束
        /// </summary>
        public const string EndStarCommentsStr = "*/";
        /// <summary>
        /// 开始大括号
        /// </summary>
        public const string BeginBigParanthesesStr = "{";
        /// <summary>
        /// 结束大括号
        /// </summary>
        public const string EndBigParanthesesStr = "}";
        /// <summary>
        /// 双引号
        /// </summary>
        public const string DoubleQuotationMarksStr = "\"";
        /// <summary>
        /// 单引号
        /// </summary>
        public const string ApostropheStr = "\'";
        /// <summary>
        /// 换行符
        /// </summary>
        public static readonly string NewlineChar_R = cNewlineChar_R.ToString();
        /// <summary>
        /// 换行符
        /// </summary>
        public static readonly string NewlineChar_N = cNewlineChar_N.ToString();
        /// <summary>
        /// 冒号
        /// </summary>
        public const string Colon = ":";
        /// <summary>
        /// 换行符
        /// </summary>
        public const char cNewlineChar_R = '\r';
        /// <summary>
        /// 换行符
        /// </summary>
        public const char cNewlineChar_N = '\n';
        /// <summary>
        /// 空格
        /// </summary>
        public const char cSpace = ' ';
        /// <summary>
        /// 制表符
        /// </summary>
        public const char cTabs = '\t';
        #endregion
        #region 关键字
        public const string KeyWord_Namespace = "namespace";
        public const string KeyWord_Class = "class";
        #endregion
        #region Parse2
        /// <summary>
        /// 使用关键信息查找,然后处理
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static CodeStructure Parse2(string code)
            CodeStructure cs = new CodeStructure();
            if (string.IsNullOrEmpty(code))
                return cs;
            //记录作用域, 后进先出
            List<CodeScope> codeScopeList = new List<CodeScope>();
            int readIndex = 0;
            List<FindIndex> findIndexList = new List<FindIndex>();
            findIndexList.Add(new FindIndex(HandleCodeType.Namespace, KeyWord_Namespace));
            findIndexList.Add(new FindIndex(HandleCodeType.Class, KeyWord_Class));
            findIndexList.Add(new FindIndex(HandleCodeType.Comments, CommentsStr));
            findIndexList.Add(new FindIndex(HandleCodeType.BeginStarComments, BeginStarCommentsStr));
            findIndexList.Add(new FindIndex(HandleCodeType.BeginBigParantheses, BeginBigParanthesesStr));
            findIndexList.Add(new FindIndex(HandleCodeType.EndBigParantheses, EndBigParanthesesStr));
            findIndexList.Add(new FindIndex(HandleCodeType.DoubleQuotationMarks, DoubleQuotationMarksStr));
            findIndexList.Add(new FindIndex(HandleCodeType.Apostrophe, ApostropheStr));
            bool isHandle = false;
            while (true)
                isHandle = false;
                //查找下标
                for (int i = 0; i < findIndexList.Count; i++)
                    findIndexList[i].Find(code, readIndex);
                //根据下标排序
                findIndexList.Sort(handleOnFindIndexSort);
                //查找除-1外最小的值处理
                for (int i = 0; i < findIndexList.Count; i++)
                    FindIndex findIndex = findIndexList[i];
                    if (findIndex.Index < 0)
                        continue;
                    readIndex = handleCode(findIndex.HandleCodeType, findIndex.Index, code, cs, codeScopeList);
                    isHandle = true;
                    break;
                if (!isHandle)
                    break;
                if (readIndex < 0)
                    break;
            return cs;
        public class FindIndex
            public HandleCodeType HandleCodeType;
            public string FindStr;
            private int index = -1;
            public int Index { get { return index; } }
            private bool noFind;
            public FindIndex(HandleCodeType handleCodeType, string findStr)
                this.HandleCodeType = handleCodeType;
                this.FindStr = findStr;
            public void Find(string code, int startIndex)
                if (noFind)
                {//未找到 不用继续找了
                    return;
                if (startIndex > Index)
                {//重新查找
                    index = code.IndexOf(FindStr, startIndex);
                    noFind = index == -1;
        private static int handleOnFindIndexSort(FindIndex x, FindIndex y)
            return x.Index - y.Index;
        #endregion
        //处理代码
        private static int handleCode(HandleCodeType handleCodeType, int matchIndex, string code, CodeStructure cs, List<CodeScope> codeScopeList)
            int readIndex = -1;
            switch (handleCodeType)
                case HandleCodeType.Namespace:
                        if (isKeyWord(matchIndex, code, KeyWord_Namespace))
                            matchIndex = skipStr(matchIndex, KeyWord_Namespace);
                            matchIndex++;//跳过一个空格
                            //找到域开始
                            int startBigParanthesesStrIndex = code.IndexOf(BeginBigParanthesesStr, matchIndex);
                            if (startBigParanthesesStrIndex < 0)
                                break;
                            string[] nameStrs = code.Substring(matchIndex, startBigParanthesesStrIndex - matchIndex).Trim().Split(new string[] { NewlineChar_R, NewlineChar_N }, StringSplitOptions.RemoveEmptyEntries);
                            if (nameStrs.Length == 0)
                                break;
                            string name = nameStrs[0];
                            //开启一个新命名空间记录
                            CodeNamespace codeNamespace = new CodeNamespace();
                            codeNamespace.Name = name;
                            CodeScope temp = new CodeScope();
                            temp.ScopeType = CodeScopeType.Namespace;
                            temp.Name = name;
                            temp.TargetObj = codeNamespace;
                            //放到对应的命名空间
                            CodeScope parentCodeScope = getLastCodeScopeByCodeScopeType(codeScopeList, CodeScopeType.Namespace);
                            if (parentCodeScope == null)
                            {//顶级命名空间域
                                cs.CodeNamespaceList.Add(codeNamespace);
                                CodeNamespace parentCodeNamespace = (CodeNamespace)parentCodeScope.TargetObj;
                                parentCodeNamespace.InternalCodeNamespaceList.Add(codeNamespace);
                            codeScopeList.Add(temp);//添加到域
                            //跳过域开始的符号位置
                            readIndex = startBigParanthesesStrIndex + 1;
                            //不是关键字,跳过
                            readIndex = skipStr(matchIndex, KeyWord_Class);
                    break;
                case HandleCodeType.Class:
                        //检查是否真的是关键字
                        if (isKeyWord(matchIndex, code, KeyWord_Class))
                            matchIndex = skipStr(matchIndex, KeyWord_Class);
                            matchIndex++;//跳过一个空格
                            //找到域开始
                            int startBigParanthesesStrIndex = code.IndexOf(BeginBigParanthesesStr, matchIndex);
                            if (startBigParanthesesStrIndex < 0)
                                break;
                            //名字 如果有冒号,使用冒号前面部分
                            string[] nameStrs = code.Substring(matchIndex, startBigParanthesesStrIndex - matchIndex).Trim().Split(new string[] { Colon, NewlineChar_R, NewlineChar_N }, StringSplitOptions.RemoveEmptyEntries);
                            if (nameStrs.Length == 0)
                                break;
                            string name = nameStrs[0];
                            CodeClass codeClass = new CodeClass();
                            codeClass.Name = name;
                            CodeScope temp = new CodeScope();
                            temp.ScopeType = CodeScopeType.Class;
                            temp.Name = name;
                            temp.TargetObj = codeClass;
                            CodeScope parentCodeScope = getLastCodeScopeByNamespaceOrClass(codeScopeList);
                            if (parentCodeScope == null)
                            {//顶级类,创建一个空名字的命名空间
                                cs.CodeClassList.Add(codeClass);
                            else if (parentCodeScope.ScopeType == CodeScopeType.Namespace)
                            {//命名空间下的类
                                ((CodeNamespace)parentCodeScope.TargetObj).CodeClassesList.Add(codeClass);
                            else if (parentCodeScope.ScopeType == CodeScopeType.Class)
                            {//内部类
                                ((CodeClass)parentCodeScope.TargetObj).InternalCodeClassList.Add(codeClass);
                            codeScopeList.Add(temp);//添加到域
                            //跳过域开始的符号位置
                            readIndex = startBigParanthesesStrIndex + 1;
                        {//不是关键字,跳过
                            readIndex = skipStr(matchIndex, KeyWord_Class);
                    break;
                case HandleCodeType.Comments:
                        matchIndex = skipStr(matchIndex, CommentsStr);
                        //因为 \r和\n都是换行符,所以都需要判断
                        //判断\r
                        int tempIndexR = indexOfStr(NewlineChar_R, false, matchIndex, code);
                        //判断\n
                        int tempIndexN = indexOfStr(NewlineChar_N, false, matchIndex, code);
                        if (tempIndexR >= 0
                            && tempIndexN >= 0)
                        {//换行符都找到,比较两个换行符哪个在前
                            if (tempIndexR < tempIndexN)
                                readIndex = skipStr(tempIndexR, NewlineChar_R);
                                readIndex = skipStr(tempIndexN, NewlineChar_N);
                        else if (tempIndexR < 0
                            && tempIndexN < 0)
                        {//换行符都没找到表示//后面没有换行符,后面的都是注释,解析结束
                            break;
                        else if (tempIndexR < 0)
                            readIndex = skipStr(tempIndexN, NewlineChar_N);
                        else if (tempIndexN < 0)
                            readIndex = skipStr(tempIndexR, NewlineChar_R);
                    break;
                case HandleCodeType.BeginStarComments:
                        matchIndex = skipStr(matchIndex, BeginStarCommentsStr);
                        readIndex = skipEndMark(EndStarCommentsStr, false, matchIndex, code);
                        if (readIndex < 0)
                        {//未找到结尾,解析结束
                            break;
                    break;
                case HandleCodeType.BeginBigParantheses:
                        matchIndex = skipStr(matchIndex, BeginBigParanthesesStr);
                        //找到当前域开始
                        CodeScope codeScope = new CodeScope();
                        codeScope.ScopeType = CodeScopeType.Other;
                        //记录该域
                        codeScopeList.Add(codeScope);
                        readIndex = matchIndex;
                    break;
                case HandleCodeType.EndBigParantheses:
                        matchIndex = skipStr(matchIndex, EndBigParanthesesStr);
                        //去掉最近的域
                        int removeIndex = codeScopeList.Count - 1;
                        CodeScope codeScope = codeScopeList[removeIndex];
                        codeScopeList.RemoveAt(removeIndex);
                        readIndex = matchIndex;
                    break;
                case HandleCodeType.DoubleQuotationMarks:
                        matchIndex = skipStr(matchIndex, DoubleQuotationMarksStr);
                        readIndex = skipEndMark(DoubleQuotationMarksStr, true, matchIndex, code);
                        if (readIndex < 0)
                        {//未找到结尾,解析结束
                            break;
                    break;
                case HandleCodeType.Apostrophe:
                        matchIndex = skipStr(matchIndex, ApostropheStr);
                        readIndex = skipEndMark(ApostropheStr, true, matchIndex, code);
                        if (readIndex < 0)
                        {//未找到结尾,解析结束
                            break;
                    break;
                default:
                    break;
            return readIndex;
        //处理代码类型
        public enum HandleCodeType
            /// <summary>
            /// 命名空间
            /// </summary>
            Namespace,
            /// <summary>
            /// 类
            /// </summary>
            Class,
            /// <summary>
            /// 双斜杠注释
            /// </summary>
            Comments,
            /// <summary>
            /// 开始星星注释
            /// </summary>
            BeginStarComments,
            /// <summary>
            /// 开始大括号
            /// </summary>
            BeginBigParantheses,
            /// <summary>
            /// 结束大括号
            /// </summary>
            EndBigParantheses,
            /// <summary>
            /// 双引号
            /// </summary>
            DoubleQuotationMarks,
            /// <summary>
            /// 单引号
            /// </summary>
            Apostrophe,
        #region Parse1
        /// <summary>
        /// 逐字匹配 太慢了
        /// 读取类结构,只有命名空间和类名
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static CodeStructure Parse1(string code)
            CodeStructure cs = new CodeStructure();
            if (string.IsNullOrEmpty(code))
                return cs;
            //记录作用域, 后进先出
            List<CodeScope> codeScopeList = new List<CodeScope>();
            int readIndex = 0;
            char readChar;//当前下标字符
            while (readIndex >= 0 &&
                readIndex < code.Length)
                readChar = code[readIndex];
                #region 判断注释 //
                if (isMatchStrIndex(CommentsStr, readIndex, code))
                    readIndex = handleCode(HandleCodeType.Comments, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                #region 判断星号注释 /*
                if (isMatchStrIndex(BeginStarCommentsStr, readIndex, code))
                    readIndex = handleCode(HandleCodeType.BeginStarComments, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                #region 判断字符串 双引号
                if (isMatchStrIndex(DoubleQuotationMarksStr, readIndex, code))
                    readIndex = handleCode(HandleCodeType.DoubleQuotationMarks, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                #region 判断字符串 单引号
                if (isMatchStrIndex(ApostropheStr, readIndex, code))
                    readIndex = handleCode(HandleCodeType.Apostrophe, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                #region 判断左大括号 域开始{ ,但是这不是命名空间域和类域的开始,因为这两种域开始用关键字判断的
                if (isMatchStrIndex(BeginBigParanthesesStr, readIndex, code))
                    readIndex = handleCode(HandleCodeType.BeginBigParantheses, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                #region 判断右大括号 域结束 }
                if (isMatchStrIndex(EndBigParanthesesStr, readIndex, code))
                    readIndex = handleCode(HandleCodeType.EndBigParantheses, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                #region 判断命名空间名
                if (isMatchStrIndex(KeyWord_Namespace, readIndex, code))
                    readIndex = handleCode(HandleCodeType.Namespace, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                #region 判断类名
                if (isMatchStrIndex(KeyWord_Class, readIndex, code))
                    readIndex = handleCode(HandleCodeType.Class, readIndex, code, cs, codeScopeList);
                    continue;
                #endregion
                readIndex++;
            return cs;
        #endregion
        /// <summary>
        /// 查找最后一个命名空间域或类域
        /// </summary>
        /// <param name="codeScopeStack"></param>
        /// <returns></returns>
        private static CodeScope getLastCodeScopeByNamespaceOrClass(List<CodeScope> codeScopeList)
            //从后往前找
            for (int i = codeScopeList.Count - 1; i >= 0; i--)
                var codeScope = codeScopeList[i];
                if (codeScope.ScopeType == CodeScopeType.Namespace ||
                    codeScope.ScopeType == CodeScopeType.Class)
                    return codeScope;
            return null;
        /// <summary>
        /// 查找最后一个指定类型的域
        /// </summary>
        /// <param name="codeScopeStack"></param>
        /// <returns></returns>
        private static CodeScope getLastCodeScopeByCodeScopeType(List<CodeScope> codeScopeList, CodeScopeType codeScopeType)
            //从后往前找
            for (int i = codeScopeList.Count - 1; i >= 0; i--)
                var codeScope = codeScopeList[i];
                if (codeScope.ScopeType == codeScopeType)
                    return codeScope;
            return null;
        /// <summary>
        /// 获得跳过匹配字符串下标
        /// </summary>
        /// <param name="readChar">当前下标值</param>
        /// <param name="str"></param>
        /// <param name="readIndex"></param>
        /// <param name="code"></param>
        /// <returns>-1 表示不匹配</returns>
        private static bool isMatchStrIndex(string matchStr, int readIndex, string code)
            char readChar = code[readIndex];
            if (readChar.Equals(matchStr[0]))
                int matchIndex = code.IndexOf(matchStr, readIndex);
                if (matchIndex == readIndex)
                {//匹配
                    return true;
            return false;
        /// <summary>
        /// 获得跳过匹配字符的下标
        /// </summary>
        /// <param name="c"></param>
        /// <param name="readIndex"></param>
        /// <param name="code"></param>
        /// <returns>-1 表示不匹配</returns>
        private static bool isMatchCharIndex(char c, int readIndex, string code)
            char readChar = code[readIndex];
            return readChar.Equals(c);
        /// <summary>
        /// 跳过以指定结束符后
        /// </summary>
        /// <param name="endMark">结束符</param>
        /// <param name="checkEscaping">是否检查转义</param>
        /// <param name="startIndex">开始下标</param>
        /// <param name="code">文字</param>
        /// <returns>结束符后的下标,如果是-1,表示未找到结束符</returns>
        private static int skipEndMark(string endMark, bool checkEscaping, int startIndex, string code)
            startIndex = indexOfStr(endMark, checkEscaping, startIndex, code);
            if (startIndex < 0)
                return startIndex;
            startIndex = skipStr(startIndex, endMark);
            return startIndex;
        private static int skipEndMark(char endMark, bool checkEscaping, int startIndex, string code)
            return skipEndMark(endMark.ToString(), checkEscaping, startIndex, code);
        //查找字符串
        private static int indexOfStr(string str, bool checkEscaping, int startIndex, string code)
            while (true)
                startIndex = code.IndexOf(str, startIndex);
                if (startIndex < 0)
                { //未找到双引号结尾,解析结束
                    break;
                if (checkEscaping
                    && code[startIndex - 1].Equals(RightSlashStr))
                {//这个字符串的前一个字符是右斜杠,表示是转义字符串,需要继续查找下一个
                    startIndex = skipStr(startIndex, str);
                    continue;
                {//找到这个结束符结束位置
                    break;
            return startIndex;
        /// <summary>
        /// 跳过该字符串
        /// </summary>
        /// <param name="index"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        private static int skipStr(int index, string str)
            return index += str.Length;
        /// <summary>
        /// 跳过该字符串
        /// </summary>
        /// <param name="index"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        private static int skipStr(int index, char c)
            return index += 1;
        //是否是关键字
        private static bool isKeyWord(int matchIndex, string code, string keyWord)
            //如果两侧字符,不是空格 制表符 换行符 就认为不是关键字
            if (matchIndex > 0)
            {//检查前面字符
                char previousChar = code[matchIndex - 1];
                if (!previousChar.Equals(cSpace)
                    && !previousChar.Equals(cTabs)
                    && !previousChar.Equals(cNewlineChar_R)
                    && !previousChar.Equals(cNewlineChar_N))
                    return false;
            if (matchIndex + keyWord.Length < code.Length - 1)
            {//检查后面字符
                char nextChar = code[matchIndex + keyWord.Length];
                if (!nextChar.Equals(cSpace)
                    && !nextChar.Equals(cTabs)
                    && !nextChar.Equals(cNewlineChar_R)
                    && !nextChar.Equals(cNewlineChar_N))
                    return false;
            return true;
        /// <summary>
        /// 代码域类型
        /// </summary>
        public enum CodeScopeType
            None = 0,
            /// <summary>
            /// 命名空间
            /// </summary>
            Namespace,
            /// <summary>
            /// 类
            /// </summary>
            Class,
            /// <summary>
            /// 其他类型域
            /// </summary>
            Other,
        /// <summary>
        /// 代码作用域
        /// </summary>
        public class CodeScope
            /// <summary>
            /// 名字
            /// </summary>
            public string Name;
            /// <summary>
            /// 作用域类型
            /// </summary>
            public CodeScopeType ScopeType;
            /// <summary>
            /// 关联容器
            /// </summary>
            public object TargetObj;
    /// <summary>
    /// 代码结构
    /// </summary>
    public class CodeStructure
        /// <summary>