【问题标题】:Parsing #regions within Code Files在代码文件中解析#regions
【发布时间】:2011-01-22 05:51:02
【问题描述】:

我正在尝试创建一个 C# 程序来提取包含在 *.cs 文件中的 #region 标记中的代码。我或多或少只是希望能够对我正在处理的代码进行注释,并让它作为文本可供其他程序访问。

是否有已经存在的东西可以做到这一点?

假设我有这样的代码:

#region ClassName.Test()
public static void Test()
{
     //Some method that does stuff
}
#endregion

我希望能够提取

public static void Test()
{
     //Some method that does stuff
}

当我指定我正在寻找 Class.Test() 时,将 *.cs 作为 string

【问题讨论】:

    标签: c# regex visual-studio-2010 parsing


    【解决方案1】:

    如果您不担心嵌套的#regions。这段代码可以解决问题。 调用 GetCodeRegions() 传入您的代码字符串(您通过使用File.ReadAlltext 获得)以获取您想要的区域内的代码 sn-ps 列表。

        static void Main(string[] args)
        {
            var code = @"#region ClassName.Test()    //Some method that does stuff
                //some stuff
                #endregion
    
                #region ClassCName.Random()
                public static void Test()
                {
                     //Some more stuff
                }
                #endregion";
    
            List<string> codeRegions = GetCodeRegions(code);
        }
    
        private static List<string> GetCodeRegions(string code)
        {
            List<string> codeRegions = new List<string>();
    
            //Split code into regions
            var matches = Regex.Matches(code, "#region.*?#endregion", RegexOptions.Singleline);
    
            foreach (var match in matches)
            {
                //split regions into lines
                string[] lines = match.ToString().Split(new string[] { "\r\n" }, StringSplitOptions.None);
    
                if (lines.Length > 2)
                {
                    codeRegions.Add(string.Join("\r\n", lines, 1, lines.Length - 2));
                }
    
            }
    
            return codeRegions;
        }
    

    【讨论】:

      【解决方案2】:

      如果您不介意潜在的麻烦问题,则只需打开文件并搜索您要查找的关键字即可。

      问题来自这样一个事实,即字符串可能包含您正在寻找的信息,但不应该被搜索。您可以尝试忽略字符串,但这可能会变得有点复杂,因为使用 " 的所有方式(\"、"" 等...)。

      如果您可以安全地忽略 C# 中的字符串,那么只需打开文本文件,逐行搜索您要查找的内容(string.Find)。

      如果您希望正确地做到这一点,那么使用 CodeDOM 是最好的选择!

      【讨论】:

        【解决方案3】:

        假设我们将整个代码放在一个字符串类代码中

        我们可以这样做

        string[] 区域 =Regex.Split("#region",classcode);

        现在区域字符串数组将包含您在访问数组时可以访问的区域代码。

        您必须从数组中的各个字符串中删除区域名称和#endregion,这不是那么麻烦

        【讨论】:

          【解决方案4】:

          我想改进目前提供的答案。 为什么? 它们都不会让开发人员轻松识别代码 sn-p 来自哪个区域。 公平地说,我已经准备了一个代码来比较目前提供的三种解决方案。 我的测试也证明了https://stackoverflow.com/users/418281/ankush-roy提供的解决方案不应该使用,因为它也可以返回不属于区域的代码。

          首先是结果:---------

          //****** Result:: Regex.Split(code, "#region")  
          public class TestRegionParsing
          {
              private void Test1()
              {
                  //this code should not be read
              }
               ClassName.Test()    
              //Some method that does stuff
              //some stuff
              #endregion ClassName.Test()
               ClassCName.Random()
              public static void Test()
              {
                   //Some more stuff
              }
              #endregion ClassCName.Random()
              private void Test2()
              {
                  //this code should not be read
              }
               ClassCName.Random()
              public static void Test3()
              {
                   //Some more stuff
              }
              #endregion
          }
          //****** Result:: GetCodeRegions(code)
          //Some method that does stuff
          //some stuff
              public static void Test()
          {
               //Some more stuff
          }
              public static void Test3()
          {
               //Some more stuff
          }
          //****** Result:: Utils.GetRegionsFromCShapFile(csharpFinePath)
          Region name converted:1.cs 
              //Some method that does stuff
              //some stuff
          Region name converted:2.cs 
              public static void Test()
              {
                   //Some more stuff
              }
          Region name converted:3.cs 
              public static void Test3()
              {
                   //Some more stuff
              }
          

          两个代码都解析的CS文件:

              public class TestRegionParsing
          {
              private void Test1()
              {
                  //this code should not be read
              }
          
              #region ClassName.Test()    
              //Some method that does stuff
              //some stuff
              #endregion ClassName.Test()
          
              #region ClassCName.Random()
              public static void Test()
              {
                   //Some more stuff
              }
              #endregion ClassCName.Random()
          
              private void Test2()
              {
                  //this code should not be read
              }
          
              #region ClassCName.Random()
              public static void Test3()
              {
                   //Some more stuff
              }
              #endregion
          }
          

          现在我已经实现了代码

          /// <summary>
              /// For a given source code, it parses all regions and creates a dictionary where 
              /// Key=region name and Value=list of region's code lines.<para />
              /// Known Issue: This method dos not work with regions within regions. <para />
              /// </summary>
              /// <param name="sourceCodeFileName">string - full source code .cs path</param>
              /// <returns>Key=region name and Value=list of region's code lines.</returns>
              public static Dictionary<string, List<string>> GetRegionsFromCShapFile(string sourceCodeFileName)
              {
                  FileInfo f = new FileInfo(sourceCodeFileName);
                  if (f.Length > ONE_Gb)
                  {
                      throw new ArgumentOutOfRangeException(string.Format("File:{0} has size greater than {1}{2}", MAX_STORAGE, STORAGE_UNIT));
                  }
                  Dictionary<string, List<String>> regions = new Dictionary<string, List<string>>();
                  string[] readLines = File.ReadAllLines(sourceCodeFileName);
                  List<string> current_list = null;
          
                  foreach (string l in readLines)
                  {
                      if (l != null)
                      {
                          if (l.TrimStart().StartsWith("#region", StringComparison.CurrentCultureIgnoreCase))
                          {
                              string key = string.Format("{0}.cs", ExtractNumber(l.Trim()));
                              if (regions.ContainsKey(key))
                              {
                                  throw new ArgumentException(string.Format("Duplicate named regions detected: {0}", l.Trim()));
                              }
                              regions[key] = new List<string>();
                              current_list = regions[key];
                          }
                          else
                          {
                              if (current_list != null) //ignores code read if it is not within a region
                              {
                                  if (l.TrimStart().StartsWith("#endregion", StringComparison.CurrentCultureIgnoreCase))
                                  {
                                      current_list = null; //stops using the current list
                                  }
                                  else
                                  {
                                      //use current list
                                      current_list.Add(l);
                                  }
                              }
                          }
                      }
                  }
          
                  return regions;
              }
          

          我希望这可能会有所帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-12-04
            • 1970-01-01
            • 2016-03-09
            • 2021-03-12
            • 2011-03-25
            • 2020-08-04
            • 2012-01-19
            相关资源
            最近更新 更多