ASP.NET Core中如何从传入方法获取控制器与方法名称?
解决方案
使用表达式树解析方法信息
直接用Action或Func<T>委托的话,编译器会把方法包装成委托实例,很难直接可靠地获取方法所属的类型信息。更合适的方式是传递表达式树,通过解析表达式树提取方法名和所属类(控制器)名称,同时支持任意返回类型的方法。
实现代码
using System.Linq.Expressions; // 处理有返回值的方法 public static string FormatMethodName<T>(Expression<Func<T>> methodExpression) { if (methodExpression.Body is not MethodCallExpression methodCall) throw new ArgumentException("必须传入方法调用表达式"); string methodName = methodCall.Method.Name; string controllerName = methodCall.Method.DeclaringType?.Name ?? throw new InvalidOperationException("无法获取方法所属类型"); // 可选:如果是ASP.NET Core控制器,自动移除"Controller"后缀 // controllerName = controllerName.EndsWith("Controller") // ? controllerName[..^10] // : controllerName; return $"{methodName}_{controllerName}"; } // 重载:处理无返回值的方法 public static string FormatMethodName(Expression<Action> methodExpression) { if (methodExpression.Body is not MethodCallExpression methodCall) throw new ArgumentException("必须传入方法调用表达式"); string methodName = methodCall.Method.Name; string controllerName = methodCall.Method.DeclaringType?.Name ?? throw new InvalidOperationException("无法获取方法所属类型"); // 可选:移除控制器后缀 // controllerName = controllerName.EndsWith("Controller") // ? controllerName[..^10] // : controllerName; return $"{methodName}_{controllerName}"; }
使用示例
public class UserController : ControllerBase { public IActionResult GetUser(int id) { return Ok(new { Id = id, Name = "Test" }); } public void LogOperation() { // 无返回值的方法 } } // 调用示例 var formatted1 = FormatMethodName(() => new UserController().GetUser(0)); // 输出:GetUser_UserController(如果开启后缀移除则是GetUser_User) var formatted2 = FormatMethodName(() => new UserController().LogOperation()); // 输出:LogOperation_UserController
为什么表达式树更适合?
- 支持任意返回类型的方法,不管是
void还是IActionResult、string等有返回值的类型。 - 能准确获取方法的所属类型,即使是静态方法也能正确解析
DeclaringType。 - 完全兼容ASP.NET Core API控制器场景——控制器本质是普通C#类,表达式树可以正常解析其方法信息。
其他可选方式(不推荐)
如果不想用表达式树,也可以直接传递MethodInfo,但调用时需要手动反射获取方法信息,代码繁琐且易出错:
public static string FormatMethodName(MethodInfo methodInfo) { string methodName = methodInfo.Name; string controllerName = methodInfo.DeclaringType?.Name ?? string.Empty; return $"{methodName}_{controllerName}"; } // 调用示例(需处理方法重载的情况) var formatted = FormatMethodName(typeof(UserController).GetMethod(nameof(UserController.GetUser), new[] { typeof(int) }));
这种方式在方法有重载时需要额外指定参数类型,不如表达式树直观安全。
内容的提问来源于stack exchange,提问作者NoddyCode
相关产品推荐
相关产品推荐

