locked
How to get Parameter names/values from MethodCallExpression? RRS feed

  • Question

  • I have the following extension method on ClientBase<T>:

     

    public static TResult Execute<TChannel, TResult>(this ClientBase<TChannel> proxy, Expression<Func<TChannel, TResult>> expr)
    	where TChannel : class
    	where TResult : class
    {
    	TResult result;
    
    	MethodCallExpression methodCall = expr.Body as MethodCallExpression;
    	if (methodCall == null)
    		throw new InvalidOperationException("Expected a method call");
    
    	logServiceCall(methodCall);
    
    	var func = expr.Compile();
    
    	try
    	{
    
    		result = func(proxy as TChannel);
    	}
    	catch (Exception ex)
    	{
    		proxy.Abort();
    		IocManager.LogManager.Error(ex, LogCategoryConstants.Common.Services.ProxyException, "Exception thrown when invoking a service", ex.Message);
    		throw;
    	}
    
    	proxy.Close();
    	return result;
    }
    

     

    Inside of the method logServiceCall I'd like to iterate of the request object's properties and log the property name and value.  Can anyone help me out?

    As a pattern each service call accepts a single argument which contains anything that needs to be passed in (ie. Name, Id, etc).

     

    private static void logServiceCall(MethodCallExpression expr)
    {
    	string methodName = expr.Method.Name;
    	string serviceContractName = expr.Object != null ? expr.Object.Type.FullName : "Undetermined service contract";
    	IocManager.LogManager.Information(LogCategoryConstants.Common.Services.ServiceCall, string.Format("Called operation {0} on service {1}", methodName, serviceContractName), string.Empty);
    
    	// TODO : Figure out how to get parameter names/values (including properties)
    	var paramters = expr.Method.GetParameters().ToList();
    	var onlyParameter = paramters.FirstOrDefault();
    	if (onlyParameter != null)
    	{
    
    	}
    }
    

     


    • Edited by Mike Paterson Wednesday, April 27, 2011 1:32 AM corrected title to MethodCallExpression
    Tuesday, April 26, 2011 9:25 PM

Answers

All replies

  • Hi Mike Paterson,

    FirstOrDefault method returns the first element of a sequence, or a default value if the sequence contains no elements, which type is TSource.

    I suggest you can check the following code snippets.

    MethodCallExpression methodCall = expr.Body as MethodCallExpression;
    MethodInfo methodInfo = methodCall.Method;
    foreach(TSource source in source)
    {
      methodInfo.Invoke(item, object array);
    }
    

    Please check here for more detailed information for MethodInfo.

    Hope this helps. If you have any finding, please feel free to let us know.

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, April 27, 2011 8:26 AM
  • An expression doesn't contain the values. Your logServiceCall needs the proxy parameter if you want the values.
    Wednesday, April 27, 2011 10:20 AM
  • Any update? Was your question solved?

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, May 3, 2011 2:59 AM
  • Larcolais,

    No this isn't solved.  I still don't know how to get the parameter values....  I saw that I can get the MethodInfo but don't know how to get the parameter values from that....

    Tuesday, May 3, 2011 11:07 AM
  • Mike,

    You dont need to worry about retrieving the argus and calling the MethodInfo yourself. You can write code like:

    MethodCallExpression<Func<MyClass, TValue>> exp = (x => x.MyMethod(p1, p2));

    object result = Expression.Lambda(exp).Compile().DynamicInvoke();

    Hope this helps.

    Esters,

    Wednesday, May 4, 2011 8:56 AM
  • Esters.  My issue isn't that I don't know how to execute the method.  I'm trying to create some verbose logging.  Part of this logging is the name and values of the parameter(s)....
    Wednesday, May 4, 2011 11:26 AM
  • Mike,

    did you check this article http://stackoverflow.com/questions/2503316/how-do-i-get-a-value-of-a-reference-type-in-an-expression/2503601?

    Adding to your latest reply, could you briefly descript your goal why did you want to use this method to create log?

    Hope this helps.

    Esters,

    Wednesday, May 4, 2011 11:48 AM
  • I haven't seen that link.  I'll check it out.  Basically I have this all over the place:

    var request = new DoSomethingRequest { Id = 5 };
    Log("Calling DoSomething with parameter Id = 5");
    
    // call service
    var response = client.Execute(c => c.DoSomething(request);
    
    string name = response.Name;
    
    Log("Received Name = " + name + " from DoSomething");
    
    I'm trying to put both log statements inside of the Execute() extension method.

    Wednesday, May 4, 2011 12:20 PM
  • By the way - be very careful logging parameter values - especially not in a service.  I could crash you in short order by spamming you with intentionally large argument values until you run out of hard disk space.  I only log parameter values to the Verbose level, and the choice to log verbose is made at the service app.config level which protects me from these types of attacks.

    Evan

    Wednesday, May 4, 2011 1:46 PM
  • Good point Evan.  This is for verbose logging.  Additionally, these services are not publicly exposed.
    Wednesday, May 4, 2011 1:50 PM
  • Mike,

    If i were you, i think i'll use Windows Service project to log everything (EventLog). Of course, it need administrator privilege to start, but you can use requiredAdministrator or other validation levels in your manifest to bypass it.

    From your said, i think it will make your server, machine, hard disk space or others heavy. ;-)

    I hope i said correct.

    Esters,

    Wednesday, May 4, 2011 2:17 PM
  • Any update? Did Esters's reply help you solve your question?

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Sunday, May 8, 2011 3:15 PM