David Henderson David Henderson - 2 months ago 17
C# Question

Is there a way to get an array of the arguments passed to a method?

Say I have a method:

public void SomeMethod(String p1, String p2, int p3)
{

#if DEBUG
object[] args = GetArguments();
LogParamaters(args);
#endif

// Do Normal stuff in the method
}


Is there a way to retrieve an array of the arguments passed into the method, so that they can be logged?

I have a large number of methods and want to avoid manually passing the arguments by name to the logger, as human error will inevitably creep in.

I'm guessing it will involve reflection in some form - which is fine, as it will only be used for debugging purposes.

Update

A little more information:

I can't change the method signature of SomeMethod, as it is exposed as a WebMethod and has to replicate the legacy system it is impersonating.

The legacy system already logs the arguments that are passed in. To start with the new implementation will wrap the legacy system, so I'm looking to log the parameters coming into the C# version, so that I can verify the right parameters are passed in in the right order.

I'm just looking to log the argument values and order, not their names.

Answer Source

Here's what I came up with as a solution:

PostSharp or another AOP solution wasn't really practical in this situation, so unfortunately I had to abandon that idea.

It appears that while it is possible to parameter names and types using reflection, the only way to access the runtime values is with a debugger attached.

See here for more info:

StackOverflow

microsoft.public.dotnet.framework

So that still left me with the problem of ~50 methods that needed this logging adding by hand.

Reflection to the rescue...

public String GetMethodParameterArray()
    {
        var output = new StringBuilder();
        output.AppendLine();

        Type t = typeof(API);
        foreach (var mi in t.GetMethods())
        {
                var argsLine = new StringBuilder();
                bool isFirst = true;
                argsLine.Append("object[] args = {");
                var args = mi.GetParameters();

                foreach (var pi in args)
                {
                    if (isFirst)
                    {
                        isFirst = false;
                    }
                    else
                    {
                        argsLine.Append(", ");
                    }
                    argsLine.AppendFormat("{0}", pi.Name);
                }
                argsLine.AppendLine("};"); //close object[] initialiser

                output.AppendLine(argsLine.ToString());
                output.AppendFormat("Log(\"{0}\",args);", mi.Name);
                output.AppendLine();
                output.AppendLine();
            }
        return output.ToString();
    }

This code snippet loops through the methods on a class and outputs an object[] array initialised with the arguments passed into the method and a Log call containing the arguments and the method name.

Example output:

object[] args = {username, password, name, startDate, endDate, cost};
Log("GetAwesomeData",args);

This block can then be pasted into the top of the method to achieve the required effect.

It is more manual than I would have liked, but it is a lot better than having to type the parameters by hand and far less error prone.