I would like to do something like this:
public MyFunction(int integerParameter, string stringParameter){ //Do this: LogParameters(); //Instead of this: //Log.Debug("integerParameter: " + integerParameter + // ", stringParameter: " + stringParameter); } public LogParameters(){ //Look up 1 level in the call stack (if possible), //Programmatically loop through the function's parameters/values //and log them to a file (with the function name as well). //If I can pass a MethodInfo instead of analyzing the call stack, great. }
I'm not even sure what I want to do is possible, but it would be very nice to be able to automatically output parameter names/values at runtime to a file without explicitly writing the code to log them.
Is it possible?
To extract the number and names of the arguments from a function or function[something] to return ("arg1", "arg2"), we use the inspect module. The given code is written as follows using inspect module to find the parameters inside the functions aMethod and foo.
func_get_args( ) returns an array of all parameters provided to the function, func_num_args( ) returns the number of parameters provided to the function, and func_get_arg( ) returns a specific argument from the parameters.
Parameters are the input variables bounded by parentheses when defining a function, whereas arguments are the values assigned to these parameters when passed into a function (or method) during a function call.
A parameter is a named variable passed into a function. Parameter variables are used to import arguments into functions. For example: function example(parameter) { console.
I realize people linked to other questions which mentioned PostSharp, but I couldn't help posting the code that solved my problem (using PostSharp) so other people could benefit from it.
class Program { static void Main(string[] args) { Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); new MyClass().MyMethod(44, "asdf qwer 1234", 3.14f, true); Console.ReadKey(); } } public class MyClass { public MyClass() { } [Trace("Debug")] public int MyMethod(int x, string someString, float anotherFloat, bool theBool) { return x + 1; } } [Serializable] public sealed class TraceAttribute : OnMethodBoundaryAspect { private readonly string category; public TraceAttribute(string category) { this.category = category; } public string Category { get { return category; } } public override void OnEntry(MethodExecutionArgs args) { Trace.WriteLine(string.Format("Entering {0}.{1}.", args.Method.DeclaringType.Name, args.Method.Name), category); for (int x = 0; x < args.Arguments.Count; x++) { Trace.WriteLine(args.Method.GetParameters()[x].Name + " = " + args.Arguments.GetArgument(x)); } } public override void OnExit(MethodExecutionArgs args) { Trace.WriteLine("Return Value: " + args.ReturnValue); Trace.WriteLine(string.Format("Leaving {0}.{1}.", args.Method.DeclaringType.Name, args.Method.Name), category); } }
Simply adding the Trace
attribute to a method will cause very nice debugging information to be output, like so:
Debug: Entering MyClass.MyMethod. x = 44 someString = asdf qwer 1234 anotherFloat = 3.14 theBool = True Return Value: 45 Debug: Leaving MyClass.MyMethod.
It's theoretically possible with a debug build and optimization turned off, but practically speaking, I suggest you want some source code rewriting pass.
People are going to keep telling you reflection will work when it won't, so here is the function that's actually capable of getting argument values. It's not likely to work reliably with optimization enabled (for example, there might not even be a stack frame when inlining is on) and getting a debugger installed so you can call that function won't be nearly as simple as you were hoping.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With