如何从Action委托外部获取其源码文件及行号并提取对应代码
解决Action委托对应源码提取问题
问题核心是当前代码读取的是整个PrintSourceCode调用的行,需要从调用行中定位并提取lambda表达式(即Action对应的代码块)。由于匿名委托的MethodInfo指向编译器生成的内部方法,无法直接获取源码位置,只能通过调用点的源码文件解析lambda块。
修改后的实现代码
using System.Text; using System.Text.RegularExpressions; static void PrintSourceCode(Action action) { action(); var frame = new StackFrame(1, true); var startLineNumber = frame.GetFileLineNumber(); var fileName = frame.GetFileName(); if (string.IsNullOrEmpty(fileName)) { Console.WriteLine("无法获取源码文件"); return; } var lines = File.ReadAllLines(fileName); var result = new StringBuilder(); int braceCount = 0; bool insideLambda = false; for (int currLineIndex = startLineNumber - 1; currLineIndex < lines.Length; currLineIndex++) { var currentLine = lines[currLineIndex]; var trimmedLine = currentLine.Trim(); // 定位lambda的起始标记 if (!insideLambda && trimmedLine.Contains("() =>")) { // 检查当前行是否包含起始大括号 var braceMatch = Regex.Match(currentLine, @"\{"); if (braceMatch.Success) { insideLambda = true; braceCount++; // 添加从大括号开始的内容 result.AppendLine(currentLine.Substring(braceMatch.Index)); } continue; } if (insideLambda) { result.AppendLine(currentLine); // 统计大括号数量 foreach (char c in currentLine) { if (c == '{') braceCount++; else if (c == '}') braceCount--; } // 当大括号闭合时退出循环 if (braceCount == 0) { break; } } } Console.WriteLine(result.ToString().TrimStart()); }
关键逻辑说明
- 定位lambda起始:从调用
PrintSourceCode的行开始,找到包含() =>的行,定位lambda的起始大括号。 - 跟踪大括号层级:通过统计
{和}的数量,处理可能的嵌套大括号,确保找到lambda块的闭合大括号。 - 提取目标内容:只保留lambda块内部的代码(包括前后大括号),过滤掉外部的
PrintSourceCode调用代码。
关于获取Action文件/行信息的说明
直接从Action委托本身无法获取对应的源码文件和行号,因为匿名委托会被编译器编译为一个内部匿名方法,其MethodInfo不包含用户源码的位置信息。必须通过调用点的StackFrame获取源码文件路径,再解析lambda块的内容。
内容的提问来源于stack exchange,提问作者beekeeper
相关产品推荐
相关产品推荐

