How to get a IDictionary of the parameters

2019-06-22 07:31发布

问题:

I would like to be able to get a list of parameters in the form of a IDictionary<string, object> of the previous method called. There is one catch: I cannot make use of third-party Aspect Oriented Programming framework even when it's free.

For example:

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Question {
    internal class Program {
        public static void Main(string[] args) {
            var impl = new Implementation();
            impl.MethodA(1, "two", new OtherClass { Name = "John", Age = 100 });
        }
    }

    internal class Implementation {
        public void MethodA(int param1, string param2, OtherClass param3) {
            Logger.LogParameters();
        }
    }

    internal class OtherClass {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    internal class Logger {
        public static void LogParameters() {
            var parameters = GetParametersFromPreviousMethodCall();
            foreach (var keyValuePair in parameters)
                Console.WriteLine(keyValuePair.Key + "=" + keyValuePair.Value);
                // keyValuePair.Value may return a object that maybe required to
                // inspect to get a representation as a string.
        }

        private static IDictionary<string, object> GetParametersFromPreviousMethodCall() {
            throw new NotImplementedException("I need help here!");
        }
    }
}

Any suggestion or ideas? Feel free to use reflection if necessary.

回答1:

You could use StackTrace to get all you need:

var trace = new System.Diagnostics.StackTrace();
var frame = trace.GetFrame(1); //previous
var method = frame.GetMethod();

Now you have a MethodBase instance.

You could get the Name by:

var method = method.Name;

and the parameters by MethodBase.GetParameters.

For example:

var dict = new Dictionary<string, object>();
foreach (var param in method.GetParameters())
{
    dict.Add(param.Name, param.DefaultValue);
}


回答2:

I think the best you can do without AOP is use the StackFrame and get the method that was called.

I imagine this would require way too much overhead. What if you passed in a variable that you modified? You would have to allocate extra space just to store the original value before it was modified within the method. That could get out of hand really quick