简体   繁体   中英

How can I get the name / details of an Action delegate invocation?

I'm testing the performance of some similar method calls that I'm wrapping in some timing and logging statements. I'm passing these methods in via an Action delegate parameter.

Is there any way to print details about the call?

For example:

var httpResult = TestService(() => serviceHttp.Search(criteria));
var tcpResult = TestService(() => serviceTcp.Search(criteria));
var localResult = TestService(() => servicelocal.Search(criteria));

...

private static double TestService(Action serviceOperation)
{
    const int iterations = 15;
    ...

    for (var i = 0; i < iterations; i++)
    {
        var watch = Stopwatch.StartNew();

        ...

        Console.WriteLine(string.Format("{0} ElapsedMilliseconds={1}", ????, watch.ElapsedMilliseconds));
         // Ideally this would print something like "serviceTcp.DoStuff(...) ElapsedMilliseconds=313"
    }

    ...
}

Change your testing method declaration to

private static double TestService(Expression<Action> expression)

Call Compile method of expression object to get a method for testing:

var serviceOperation = expression.Compile();

Expression object can provide a lot of information about method call, you can start with something like this:

private static string GetMethodCallDescription(Expression<Action> expression)
{
    var mce = (MethodCallExpression)expression.Body;
    var method = mce.Method;
    var sb = new StringBuilder();
    sb.Append(method.DeclaringType.Name);
    sb.Append(".");
    sb.Append(method.Name);
    sb.Append("(");
    bool firstarg = true;
    foreach(var arg in mce.Arguments)
    {
        if(!firstarg)
        {
            sb.Append(", ");
        }
        else
        {
            firstarg = false;
        }
        sb.Append(arg.ToString());
    }
    sb.Append(")");
    return sb.ToString();
}

You could do it without using expression trees; just change the signature of TestService to take the action and the parameter separately, and use the Delegate.Target and Delegate.Method properties to get the type and method:

var httpResult = TestService(serviceHttp.Search, criteria);
var tcpResult = TestService(serviceTcp.Search, criteria);
var localResult = TestService(servicelocal.Search, criteria);

...

private static double TestService<T>(Action<T> serviceOperation, T parameter)
{
    const int iterations = 15;
    ...

    for (var i = 0; i < iterations; i++)
    {
        var watch = Stopwatch.StartNew();

        ...

        string typeName = serviceOperation.Method.IsStatic
                          ? serviceOperation.Method.DeclaringType.Name
                          : serviceOperation.Target.GetType().Name;
        string methodName = serviceOperation.Method.Name;
        Console.WriteLine(string.Format("{0}.{1} ElapsedMilliseconds={2}", typeName, methodName, watch.ElapsedMilliseconds));
         // Ideally this would print something like "serviceTcp.DoStuff(...) ElapsedMilliseconds=313"
    }

    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM