如何获取调用方法的参数值?

我正在编写一些代码,需要能够从调用类的方法中获取参数的 。 我知道如何一直到ParameterInfo []数组,但我不知道如何获取值。 这有可能吗?

如果是,我认为它与使用MethodInfo对象的MethodBody属性有关,它允许你检查IL流,包括属性,但我不知道怎么做,我还没有找到适用于Google的代码。

// Finds calling method from class that called into this one public class SomeClass { public static void FindMethod() { for (int i = 1; i < frameCount; i++) { var frame = new StackFrame(i); var methodInfo = frame.GetMethod(); if (methodInfo.DeclaringType != this.GetType()) { string methodName = frame.GetMethod().Name; var paramInfos = methodInfo.GetParameters(); // Now what?? How do I get the values from the paramInfos break; } else if (i == frameCount - 1) { throw new TransportException("Couldn't find method name"); } } } } 

如果不自己反省堆栈就不能这样做(这很脆弱,因为许多优化可能意味着堆栈帧不是你所期望的,或者甚至传递的参数实际上不是方法签名所暗示的(这完全可能是一个优化的JIT编译器,发现你只使用了一个对象/结构的子字段并传递了它。

ParameterInfo只是告诉您编译方法的签名 ,而不是传递的值。

实现这一目标的唯一现实方法是通过代码注入(通过像AOP这样的东西)来创建数据,并根据分析IL做你想做的事情。

这通常不是一个好主意,如果你需要使用调试器调试一些东西,如果你需要记录一些关于你正在记录的内容。

要清楚,简单的反光技术无法实现你想要的完全通用性

微软的Jonathan Keljo在这篇新闻组post中说:

不幸的是,今天从callstack获取参数信息的唯一简单方法是使用调试器。 如果您尝试将此操作作为应用程序中的错误日志记录的一部分,并且您计划将错误日志发送回支持部门,我们希望将来您可以将minidump用于此目的。 (今天,使用带有托管代码的minidump有点问题,因为它没有包含足够的信息来默认甚至获得堆栈跟踪。带堆的minidump更好,但如果你知道我的意思,那就不那么“迷你”。)

一个纯粹主义者会说允许人们编写可以从callstack其他地方的函数获取参数的代码将鼓励他们打破封装并创建在变化面前非常脆弱的代码。 (你的场景没有这个特殊问题,但我听说过这个function的其他请求。无论如何,大多数请求都可以通过其他方式解决,比如使用线程存储。)然而,更重要的是会有安全隐患这一点 – 允许插件的应用程序将面临那些插件为敏感信息抓取堆栈的风险。 我们当然可以将该function标记为需要完全信任,但这会使我几乎无法用于所有我听说过的场景。

乔纳森

所以…我想简短的回答是“我不能。” 太糟糕了。

是的,你可以这样做。

您需要做的是使用IL反汇编程序(可在System.Reflection.Emit命名空间中实现)来查找包含您正在查找的参数值的操作数。

从这个问题开始: C#reflection并找到所有引用

然后使用答案中提到的类(来自Mono.Reflection)进行检查。 像这样的东西:

  var instructions = method.GetInstructions(); foreach (var instruction in instructions) { var methodInfo = instruction.Operand as MethodInfo; if(methodInfo == null) { continue; } if (instruction.OpCode.Name.Equals("call") && methodInfo.Name.Equals("YourMethodHere")) { var value = (CastToMyType)instruction.Previous.Operand; // Now you have the value... } } 

您无法使用StackFrame或StackTrace执行此操作。 但是,您可以使用一些拦截框架(例如Spring.NET中的AOP),以便您可以获取参数值。

看这里:

你能在C#中获得堆栈上的变量列表吗?

基于对我的答案的所有评论,我不认为这是可能的。 PropertyInfo类有一个GetValue方法,但这需要您拥有一个要从中获取值的实际对象。