【问题标题】:c# regex - select class properties names, methods name and fields from class file (.cs)c# regex - 从类文件 (.cs) 中选择类属性名称、方法名称和字段
【发布时间】:2012-08-11 11:53:34
【问题描述】:

我想匹配(从类文件中选择)方法名、属性名和字段名。

这是示例类:

class Perl
{
    string _name;
    public string Name { get; set; }
    public Perl()
    {
    // Assign this._name
    this._name = "Perl";
    // Assign _name
    _name = "Sam";

    // The two forms reference the same field.
    Console.WriteLine(this._name);
    Console.WriteLine(_name);
    }
    public static string doSomething(string test)
    {
        bla test;
    }
}

我得到了方法的代码:

(?:public|private|protected)([\s\w]*)\s+(\w+)\s*\(\s*(?:\w+\s+(\w+)\s*,?\s*)+\)

我有问题:

  • 上面的正则表达式代码获取了所有方法,它工作得很好,但是 我也希望它选择方法名称但没有参数和 访问器。所以从 exaplmce 类使用我的代码结果将是: public Perl()public static doSomething(string test) 但我想要那种结果:Perl()doSomething( )。所以 - 我的代码匹配得很好,但我希望结果像我一样显示 写在上一句。
  • 如何选择属性?显示结果:类型和属性 姓名。所以从 exaple 类结果将是: string Name
  • 如何选择具有结果的字段:键入字段名称。万一它 将是:字符串_名称

【问题讨论】:

  • 可能与this SO answer重复
  • 在编译的类上使用反射而不是代码文件上的正则表达式是否有意义?您将获得更可靠的结果(即您不必担心您的正则表达式命令是否涵盖所有可能的情况),并且它可以与任何 .NET 语言一起使用,而不仅仅是 C#。
  • 所以我得到了带有 .cs 类文件的文件夹。我可以“在空中”编译它然后使用反射吗?例如,如何动态编译类是否有我可以使用的函数?例如。在按钮上单击comile所选文件夹中的所有cs文件?

标签: c# regex properties methods match


【解决方案1】:

使用这个Regex

方法

(?:public\s|private\s|protected\s|internal\s)?[\s\w]*\s+(?<methodName>\w+)\s*\(\s*(?:(ref\s|/in\s|out\s)?\s*(?<parameterType>\w+)\s+(?<parameter>\w+)\s*,?\s*)+\)

并获取名为 methodNameparameterTypeparameter 的组。

对于字段:

(?:public\s|private\s|protected\s)\s*(?:readonly\s+)?(?<type>\w+)\s+(?<name>\w+)

并获取名为 typename 的组。

例如,您的方法代码可以是这样的:

var inputString0 = "public void test(string name, out int value)\r\nvoid test(string name, int value)";
foreach (Match match in Regex.Matches(inputString0, @"(?:public\s|private\s|protected\s)?[\s\w]*\s+(?<methodName>\w+)\s*\(\s*(?:(ref\s|/in\s|out\s)?\s*(?<parameterType>[\w\?\[\]]+)\s+(?<parameter>\w+)\s*,?\s*)+\)"))
{
    var methodName = match.Groups["methodName"].Value;
    var typeParameterPair = new Dictionary<string, string>();
    int i = 0;
    foreach (var capture in match.Groups["parameterType"].Captures)
    {
        typeParameterPair.Add(match.Groups["parameterType"].Captures[i].Value, match.Groups["parameter"].Captures[i].Value);
        i++;
    }
}

您也可以使用 codeplex 中的Irony - .NET Language Implementation Kit

【讨论】:

  • 但是属性和文件呢? ;)
  • 可见范围internal怎么样?
  • 我不能使用讽刺;)。我在我的应用程序中使用 NET 2.0。感谢字段正则表达式代码。我将尝试修改它以匹配属性(在 {} 中使用 get 或 set)
  • @Ria 字段呢?那是最难的部分。我只是不知道如何使用正则表达式从 .cs 文件中读取字段。我总是得到所有变量,即使是在方法中声明的变量。
【解决方案2】:

正如 cmets 对您的回答所说,更可靠的方法是编译您的 .cs 文件,然后使用反射来询问您感兴趣的成员的类型。它将涉及以下内容:

  1. 使用 C# 编译器 (csc.exe) 编译您的文件。 MSDN 包含有用的examples and hints。您可以手动执行此操作,或者,如果您想自动化整个操作,您可以使用 Process class 以编程方式执行 csc.exe。
  2. 使用Assembly.LoadFile() 方法加载生成的程序集。
  3. 您现在可以对程序集中的get typesinterrogate 它们使用反射。

编辑:作为 csc.exe 的替代方案,您可以使用 CodeDOM - example 包含您需要的所有内容。

【讨论】:

  • 我不久前问过类似的问题,关于如何使用反射方法获取参数值,但遗憾的是没有有用的答案。这甚至可能吗?因为那将是代替正则表达式的方法。
  • @user1010609 我不明白这与这个问题有什么关系 - 但发布链接,我可以看看。
  • 这不相关,但可以说他想做这样的事情Console.WriteLine(_name);,有没有办法得到_name 的值是什么?如果它是像Console.WriteLine("John"); 这样的硬编码?因为正则表达式可以轻松做到这一点,但会使其他事情变得更加复杂,只是想为他指明正确的方向。
  • 我想在我的程序中使用它(所以我不能只启动另一个程序)它必须自动完成;)。我需要将所有方法、属性和字段名称写入 xml。使用 csc.exe 看起来很复杂
【解决方案3】:

诸如 C# 之类的语言接受的语句语法变化太多,只能使用正则表达式进行解析。除了正则表达式,您还需要一个上下文语法解析器。

我想试试Roslyn:它是一个 C# 编译器,其内部结构可从您的代码中访问。让 Roslyn 解析代码并查询您需要的任何信息。

【讨论】:

    【解决方案4】:

    我建议查看Microsoft.VisualStudio.CSharp.Services.Language 命名空间和其他Visual Studio 可扩展性 功能。这将消除编译的需要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      相关资源
      最近更新 更多