2012-08-11 126 views
5

我想匹配(从类文件中选择)methodsname,属性名称和字段名称。c#正则表达式 - 从类文件(.cs)中选择类属性名称,方法名称和字段

这是示例类:

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类: 公众的Perl()公共静态DoSomething的(字符串测试),但我想这样的结果:的Perl()DoSomething的()。所以 - 我的代码匹配很好,但我想要显示的结果就像我在前面的句子中写的 。
  • 如何选择属性?结果显示:类型和属性 名称。因此,从实例级结果将是:字符串名称
  • 如何选择带结果的字段:type field_name。在出情况下, 将是:字符串_name
+1

可能是[This SO Answer](http://stackoverflow.com/a/11647554/1495442) – Ria 2012-08-11 12:03:19

+0

的重复在代码文件上使用反射而不是正则表达式编译的类可能有意义吗?你会得到更可靠的结果(即你不必担心你的正则表达式命令是否覆盖了每种可能的情况),它可以用于任何.NET语言,而不仅仅是C#。 – 2012-08-11 12:06:56

+0

所以我得到.cs类文件的文件夹。我可以编译它“在空气中”,然后使用反射?如何动态编译类例如是否有我可以使用的函数?例如。在按钮上单击comile选定文件夹中的所有cs文件? – born2fr4g 2012-08-11 12:30:31

回答

3

使用此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++; 
    } 
} 

您可以使用Irony - .NET Language Implementation KitCodePlex上了。

+0

但是属性和文件呢? ;) – born2fr4g 2012-08-11 12:31:23

+0

能见度范围'internal'呢? – 2012-08-11 14:52:04

+0

我不能使用讽刺;)。我在我的应用程序中使用NET 2.0。感谢您的字段正则表达式代码。我将尝试修改它以匹配属性(使用get或set ** **}) – born2fr4g 2012-08-12 07:31:18

2

正如在评论你的答案说明,更可靠的方法是编译的.cs文件,然后使用反射来询问类型的会员你有兴趣在这将涉及以下内容:

  1. 使用C#编译器(csc.exe)来编译你的文件。 MSDN包含有用的examples and hints。您可以手动执行此操作,或者,如果您想自动整理所有内容,则可以使用Process class以编程方式执行csc.exe。
  2. 使用Assembly.LoadFile()方法加载生成的程序集。
  3. 您现在可以使用反射到get types从大会和interrogate他们。

编辑:作为替代CSC.EXE,你可以使用CodeDOM - 有一个包含所有你需要的example

+0

前一段时间我问过类似的问题,关于如何使用反射方法获取参数值,但很遗憾没有有用的答案。这甚至有可能吗?因为这将是取代正则表达式的方法。 – formatc 2012-08-11 14:54:10

+0

@ user1010609我不明白这与这个问题有什么关系 - 但发布链接,我可以看看它。 – 2012-08-11 15:27:20

+0

这是不相关的,但让我们说他想要做这样的事情'Console.WriteLine(_name);',有没有办法得到'_name'值是什么?如果硬编码像Console.WriteLine(“John”);'?因为正则表达式可以轻松地做到这一点,但让其他事情变得更加复杂,只是想让他指向正确的方向。 – formatc 2012-08-11 16:01:54

0

像C#这样的语言接受太多的语法语法变体,只能使用正则表达式进行解析。在正则表达式之上,你需要一个上下文语法分析器。

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

0

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