How can I get the values of the parameters of a calling method?

Jonathan Keljo at Microsoft says, in this news group post, :

Unfortunately, the only easy way to get argument information from a callstack today is with a debugger. If you're trying to do this as part of error logging in an application and you plan to send the error log back to your support department, we're hoping to have you use minidumps for that purpose in the future. (Today, using a minidump with managed code is a little problematic as it does not include enough information to even get a stack trace by default. A minidump with heap is better, but not so "mini" if you know what I mean.)

A purist would say that allowing people to write code that can get arguments from functions elsewhere on the callstack would encourage them to break encapsulation and create code that's very fragile in the face of change. (Your scenario does not have this particular problem, but I've heard other requests for this feature that would. Anyway most of those requests can be solved in other ways, like using thread stores.) However, more importantly there would be security implications of this--applications that allow plugins would be at risk of those plugins scraping the stack for sensitive information. We could certainly mark the function as requiring full-trust, but that would make it unusable for pretty much every scenario I've heard of.

Jonathan

So... I guess the short answer is "I can't." That sucks.


You cannot do it without introspecting the stack yourself (and this is fragile since many optimizations may mean the stack frame is not what you expect, or even that the parameter passed is not in fact what the method signature would suggest (it is perfectly possible for an optimizing JIT compiler to spot that you are only using a sub field of an object/struct and pass that instead).

The ParameterInfo simply tells you the signature of the method as compiled, not the values that were passed.

The only realistic way to achieve this automatically is via code injection (via something like AOP) to create the data and do what you want with it based on analysing the IL.

This is generally not a good idea, if you need to debug something use a debugger, if you need to log something be explicit about what you are logging.

To be clear simple reflective techniques cannot achieve what you desire with full generality


Yes, you can do this.

What you need to do is use an IL disassembler (which is achievable within the System.Reflection.Emit namespace) to find the Operand that contains the parameter value you're looking for.

Start with this SO question: C# reflection and finding all references

Then use the class mentioned in the answers (from Mono.Reflection) to do your inspection. Something like this:

            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...
                }
            }