如何获取Action委托调用的名称/详细信息?

时间:2012-05-08 22:01:53

标签: c# c#-4.0

我正在测试一些类似的方法调用的性能,我将其包含在一些时序和日志语句中。我通过Action delegate参数传递这些方法。

有没有办法打印有关通话的详细信息?

例如:

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"
    }

    ...
}

2 个答案:

答案 0 :(得分:4)

将测试方法声明更改为

private static double TestService(Expression<Action> expression)

调用表达式对象的Compile方法来获取测试方法:

var serviceOperation = expression.Compile();

Expression对象可以提供很多关于方法调用的信息,你可以从这样的东西开始:

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();
}

答案 1 :(得分:2)

你可以不使用表达式树来做到这一点;只需更改TestService的签名即可单独执行操作和参数,并使用Delegate.TargetDelegate.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"
    }

    ...
}