从许多文件中检索方法/代码

时间:2010-06-23 09:01:24

标签: c# methods web-crawler

我有很多.cs文件,我想自动从这些文件中检索[AcceptVerbs(HttpVerbs.Post)]属性背后的方法。

所以输入是:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult sample(string msg)
{......}

,输出为:

public ActionResult sample(string msg)
{......}

我的想法是使用RegularExpressions和String.IndexOf找到属性的位置 并计算{和}以找到方法的开始和结束位置,以便检索方法。

还有其他方法可以帮助我(图书馆,工具或方法)吗?

非常感谢。

2 个答案:

答案 0 :(得分:1)

不确定这是否是您想要的,但您可以使用反射

public static IList<MemberInfo> GetMethodsImplementing<T>(Assembly assembly) where T : Attribute
{
    var result = new List<MemberInfo>();

    var types = assembly.GetTypes();
    foreach (var type in types)
    {
        if (!type.IsClass) continue;

        var members = type.GetMembers();
        foreach (var member in members)
        {
            if (member.MemberType != MemberTypes.Method)
                continue;

            var attributes = member.GetCustomAttributes(typeof(T), true /*inherit*/);
            if (attributes.Length > 0)
            {
                // yup. This method implementes MyAttribute
                result.Add(member);
            }
        }
    }

    return result;
}

答案 1 :(得分:0)

假设这只是一次性而且您的源是“平衡的”(源文件中等量的{}),您可以使用正则表达式平衡。

此代码段只需一个文件并在其中检查任何.. class .. { .. }并将其作为String[]返回。

您必须修改它以匹配最后的linq查询中的AcceptVerbs(HttpVerbs.Post)。通过你的目录递归并为每个.cs文件执行此操作我假设你有代码。最后,您可能还需要稍微修改一下并使用rx更多/更少次数,具体取决于您要开始查看的{}级别。

此测试片段是在LinqPad中制作的,您可以下载它并通过将语言设置为C# Program来测试它,将其移动到打印到文件或类似文件的控制台应用程序中,但应该很简单。

void Main()
{
    String data = String.Empty;
    using (StreamReader reader = new StreamReader(@"/path/to/a/file.cs"))
        data = reader.ReadToEnd();

    CheckContents(data, "class").Dump();
}

// Define other methods and classes here
String[] CheckContents(String data, String pattern)
{
    var rx = new Regex(@"{
    (?>
        { (?<DEPTH> )
        |
        } (?<-DEPTH> )
        |
        [^}{]*
    )*
    (?(DEPTH)(?!))
    }", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

    var rx2 = new Regex(@"[^{]*{
    (?>
        { (?<DEPTH> )
        |
        } (?<-DEPTH> )
        |
        [^}{]*
    )*
    (?(DEPTH)(?!))
    }", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

    var nameSpace = rx.Match(data).Value.Substring(1); // Remove { from namespace so we don't match the same thing over and over
    var parts = rx2.Matches(nameSpace);

    return (from Match part in parts where Regex.IsMatch(part.Value, pattern) select part.Value.Trim()).ToArray();
}