2012-07-25 53 views
1

我想匹配方法名称(带参数)和属性名称。我不想在匹配中包含访问器。 例如我有这种类:Regex C# - 如何匹配一个类的方法和属性名称

public class test 
{ 
    public static string NA = "n/a"; 

    public static DateTime DateParser(string dateToBeParsed) 
    { 
     DateTime returnValue = new DateTime(); 
     DateTime.TryParse(dateToBeParsed, GetCulture(), System.Globalization.DateTimeStyles.AssumeLocal , out returnValue); 
     return returnValue; 
    } 
} 

的类名是我使用这种正则表达式的:(?< = A类\ S)[^ \ S] +的方法我尝试的东西像这样:[^ \ s] +(?=()但是这将选择所有文本有。对于方法,我需要选择该行有和访问者像公共,私人和保护。如何在最终匹配中不包含此内容?我只需要括号内的方法名称和参数。

回答

1

用正则表达式来做这件事相当困难。

您可以尝试改为创建合适的分析器。 Irony库易于使用,其中一个示例是C#解析器。

但是,如果你想使用正则表达式,你可以尝试使用像Expresso这样的工具,它可以帮助你测试和构建正则表达式。

你还应该写很多单元测试 - 修改正则表达式时很容易破坏某些东西。

对不起,不提供的那种“具体的”帮助“用这句话”,但我认为,如果你想避免解析器它真的很多工作:)

+0

Thx的提示,但我需要这样做自动;)。我需要从.cs文件中将这些信息写入到txt/xml文件中。说实话,访问者和关键字这个任务不应该很难。或者也许你知道更简单的方法来做到这一点?从cs(类文件)属性和方法名称中取回) – born2fr4g 2012-07-25 07:17:56

+0

@ born2fr4g:为什么不是自动的? :) 检查图书馆和它的例子,这是真的值得,不应该花很长时间。正则表达式的风险是,在一种情况下工作的东西不足以处理另一个有效的案例。 – 2012-07-25 07:26:14

+0

但是我得到了2.0 NET项目,但Irony需要NET 4.0以及如何使用它?这个缺少一个文档:) – born2fr4g 2012-07-25 08:56:04

2

编辑的:使用此Regex

(?: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*)+\) 

,并获得命名methodNameparameterTypeparameter组。

你的代码可以是这样的:

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++; 
    } 
} 
+0

不错,但是'void test(string name,int value)'和'public void test(string name,out int value)' - 这些都是有效的声明吗? – 2012-07-25 11:44:47

+0

@PaoloTedesco:感谢您的关注。我更新了我的答案 – Ria 2012-07-25 11:50:52

+0

另外两个:'void test(string name,int [] value)'和'void test(string name,params int [] value)'。我不想成为一个痛苦,我只是想表明我的观点:现在没事的事情会在某种情况下分崩离析,你没有想到:) – 2012-07-25 12:01:44

3

关于使用反射如何?

class Program 
{ 
    static void Main(string[] args) 
    { 
     string assemblyName = Path.Combine(Path.GetTempPath(), string.Format("temp{0}.dll", Guid.NewGuid())); 
     CSharpCodeProvider codeProvider = new CSharpCodeProvider(); 
     CompilerParameters compilerParameters = new CompilerParameters(new string[] 
     { 
      "System.dll", 
      "Microsoft.CSharp.dll", 
     }, assemblyName); 

     CompilerResults cr = codeProvider.CompileAssemblyFromSource(compilerParameters, File.ReadAllText("Program.cs")); 

     if (cr.Errors.Count > 0) 
     { 
      foreach (CompilerError error in cr.Errors) 
      { 
       Console.WriteLine(error.ErrorText); 
      } 
     } 
     else 
     { 
      AppDomain appDomain = AppDomain.CreateDomain("volatile"); 
      Proxy p = (Proxy)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Proxy).FullName); 
      p.ShowTypesStructure(assemblyName); 
      AppDomain.Unload(appDomain); 
      File.Delete(assemblyName); 
     } 
     Console.ReadLine(); 
    } 
} 

public class Proxy : MarshalByRefObject 
{ 
    public void ShowTypesStructure(string assemblyName) 
    { 
     Assembly assembly = Assembly.LoadFrom(assemblyName); 
     Type[] types = assembly.GetTypes(); 
     foreach (Type type in types) 
     { 
      Console.WriteLine(type.Name); 
      MethodInfo[] mis = type.GetMethods(); 
      foreach (MethodInfo mi in mis) 
      { 
       Console.WriteLine("\t" + mi.Name); 
      } 
     } 
    } 
} 
+0

我认为他试图解析的类不是执行程序集的一部分,但动态编译代码并使用反射可能是个好主意...... – 2012-07-25 11:47:50

+0

更新答案以包含动态编译。 – Paciv 2012-07-25 12:28:08

+0

我无法尝试,但我喜欢它:)从我+1! – 2012-07-25 13:24:57

相关问题