C# 使用正则表达式在源代码中查找方法
我有一个程序,它查找源代码,查找方法,并对每个方法内部的代码执行一些计算。我正试图使用正则表达式来实现这一点,但这是我第一次在C#中使用它们,而且我很难测试结果 如果使用此正则表达式查找方法签名:C# 使用正则表达式在源代码中查找方法,c#,regex,C#,Regex,我有一个程序,它查找源代码,查找方法,并对每个方法内部的代码执行一些计算。我正试图使用正则表达式来实现这一点,但这是我第一次在C#中使用它们,而且我很难测试结果 如果使用此正则表达式查找方法签名: ((private)|(public)|(sealed)|(protected)|(virtual)|(internal))+([a-z]|[A-Z]|[0-9]|[\s])*([\()([a-z]|[A-Z]|[0-9]|[\s])*([\)|\{]+) 然后使用此方法拆分源代码,将结果存储在字符
((private)|(public)|(sealed)|(protected)|(virtual)|(internal))+([a-z]|[A-Z]|[0-9]|[\s])*([\()([a-z]|[A-Z]|[0-9]|[\s])*([\)|\{]+)
然后使用此方法拆分源代码,将结果存储在字符串数组中:
string[] MethodSignatureCollection = regularExpression.Split(SourceAsString);
这能满足我的需求吗,比如一系列方法,包括其中的代码?我强烈建议使用(如果合适)或(按照rstevens的建议) 编写一个在所有情况下都能工作的正则表达式可能非常困难 以下是您必须处理的一些情况:
public /* comment */ void Foo(...) // Comments can be everywhere
string foo = "public void Foo(...){}"; // Don't match signatures in strings
private __fooClass _Foo() // Underscores are ugly, but legal
private void @while() // Identifier escaping
public override void Foo(...) // Have to recognize overrides
void Foo(); // Defaults to private
void IDisposable.Dispose() // Explicit implementation
public // More comments // Signatures can span lines
void Foo(...)
private void // Attributes
Foo([Description("Foo")] string foo)
#if(DEBUG) // Don't forget the pre-processor
private
#else
public
#endif
int Foo() { }
注意事项:
方法将丢弃它匹配的所有内容,因此实际上,您将丢失正在拆分的所有“签名”Split
- 不要忘记签名中可以有逗号
- 如果可以嵌套,
,则当前regexp消耗的{…}
可能比它应该消耗的更多{
- 还有很多其他东西(预处理器命令,
语句、属性、注释、使用
定义、属性)可以显示在代码中,因此,仅仅因为某些东西位于两个方法签名之间,并不能使其成为方法体的一部分enum
var methods = typeof (Foo).GetMethods();
foreach (var info in methods)
{
var body = info.GetMethodBody();
}
这可能就是你计算所需要的
如果你需要原始的C#源代码,你无法通过反射获得。不要编写你自己的解析器。使用一个现有的解析器,如清单所示。我想,使用正则表达式工作是可行的,但是这确实需要非常仔细地查看C#语言的规范,并深入理解C#语法,这是正确的不是一个简单的问题。我知道你说过你想把这些方法存储为字符串数组,但是大概还有一些东西超出了它。它已经被指出要使用反射,但是如果它不做你想要的,你应该考虑ANTLR(另一种语言识别工具)。.ANTLR确实有C#语法可用
使用CSharpCodeProvider.Parse()可能是一种更好的方法,它可以将C#源代码“编译”成编译器单元。
然后,您可以在该编译单元中遍历的名称空间、类型、类和方法。使用
ICSharpCode.nreactory.CSharp;
PM>安装包ICSharpCode.nFactory
var parser = new CSharpParser();
var syntaxTree = parser.Parse(File.ReadAllText(sourceFilePath));
var result = syntaxTree.Descendants.OfType<MethodDeclaration>()
.FirstOrDefault(y => y.NameToken.Name == methodName);
if (result != null)
{
return result.ToString(FormattingOptionsFactory.CreateSharpDevelop()).Trim();
}
var parser=new CSharpParser();
var syntaxTree=parser.Parse(File.ReadAllText(sourceFilePath));
var result=syntaxTree.subjects.OfType()的
.FirstOrDefault(y=>y.NameToken.Name==methodName);
如果(结果!=null)
{
返回result.ToString(formatingoptionsfactory.CreateSharpDevelop()).Trim();
}
实际上,普通正则表达式无法解决这个问题,因为它们不能计数。(不过,Perl“正则表达式”是图灵完备的。)