anaximander
anaximander

Reputation: 7140

Get names of parameters in method (and use as Dictionary keys?)

I'm writing an audit logging system to be integrated into an existing piece of software, and the database structure includes a field for a blob of detail about the action being logged. Doesn't have to be anything fancy; it won't be needed much, and when it is, in most cases it'll be read by the devs to find out which method was called and with what parameters, stuff like that. This means that while it should probably be human-readable, it doesn't need to be parsed by anything. So, rather than have lots of overloads, or use horrible switch case string replacements, I figured a nice way to write the detail blob would be for a logging call to get the names of the parameters required by the action being logged, and the values that were passed to them. I've done some research, and found something promising in the reflection methods, but I've yet to find anything that explains clearly how to do it.

Here's a rough mock of what I'm after:

Dictionary<string,string> parameters = new Dictionary<string,string>();
foreach (Parameter p in MethodCall)
{
    parameters.Add(p.Name, p.Value.ToString());
}

LogEvent(EventType.Something, userID = thisUser, details = parameters);

I understand it's likely to be more complex than that in practice, but it gives you the general idea. Inside my LogEvent method there's some stuff to add timestamps, construct descriptive sentences for the user-end log viewer (less technical detail than we show to admins and devs, so as not to expose our program/database structure) and - in theory - build some kind of blob (probably JSON or similar) from the Dictionary of parameter details.

Upvotes: 3

Views: 1475

Answers (4)

Panos Rontogiannis
Panos Rontogiannis

Reputation: 4172

Why don't you try PostSharp? It is meant to solve problems like yours. In the samples you will find a logging aspect that prints parameter values. Combined with XML configuration, will allow the administrator/user to enable logging/tracing at will.

Upvotes: 0

Fredrik Claesson
Fredrik Claesson

Reputation: 629

I would use a Interceptor (Castle.DynamicProxy) like in my example below:

  internal class Program
  {
    private static void Main(string[] args)
    {

      var interceptor = new Interceptor();
      var businessObjectClass = new ProxyGenerator().CreateInterfaceProxyWithoutTarget<IBusinessObjectClass>(interceptor);

      businessObjectClass.Method3("what",123);

      Console.ReadLine();
    }
  }

  public class Interceptor : IInterceptor
  {
    #region IInterceptor Members

    public void Intercept(IInvocation invocation)
    {
      Console.WriteLine(string.Format("Intercepted call to: " + invocation.Method.Name));
      foreach (var argument in invocation.Arguments)
      {
        Console.WriteLine(string.Format("\t Param: " + argument.ToString()));
      }
      invocation.Proceed();
    }

    #endregion
  }

  public interface IBusinessObjectClass
  {
    void Method3(string stringValue, int intValue);
  }

  public class BusinessObjectClass : IBusinessObjectClass
  {

     public void Method3(string stringValue, int intValue)
    {
      return;
     }

  }

DynamicProxy

Upvotes: 1

tukaef
tukaef

Reputation: 9214

If your logging method takes an expression parameter, you can get parameter names and values by this code:

static void LogSomething(Expression<Action> expression)
{
    var methodCallExpression = ((MethodCallExpression) expression.Body);
    var parameterNames = methodCallExpression.Method.GetParameters().Select(p => p.Name);
    var values = methodCallExpression.Arguments.Select(a => a.Value);
}

Upvotes: 1

Jason Kleban
Jason Kleban

Reputation: 20808

Related is: Obtain parameter values from a stack frame in .NET? which has some useful answers.

You want to log the method name and the parameter list. The method name is easy using StackFrame but I don't think you can use simple reflection to get the parameter values out.

Upvotes: 1

Related Questions