c# - (Action<T>).Name 不返回预期值

标签 c# generics delegates

我有以下方法(用于在单元测试中生成友好的错误消息):

protected string MethodName<TTestedType>(Action<TTestedType> call)
{
    return string.Format("{0}.{1}", typeof(TTestedType).FullName, call.Method.Name);
}

但是当我如下调用它时,我没有得到预期的结果:

var nm = MethodName<MyController>(ctrl => ctrl.Create());

运行此代码后,nm包含 "<Create_CreateShowsView>b__8" ,而不是(如预期的那样)"Create" .我应该如何更改代码以获得预期的结果?

最佳答案

您需要传递一个 Expression而不是 Action .一旦您了解树的外观,使用表达式树实际上并不难。

代码行:

(MyClass c) => c.TestMethod();

可以分解为一个 lambda 表达式(整个 block ),包含一个参数(c,在左侧)和一个正文(c.TestMethod(),在右侧)。

“正文”是对特定对象的方法调用(即参数 c )、实际方法( TestMethod )和一组参数(在本例中,没有任何)。

视觉上:

            LambdaExpression   [ (MyClass c) => c.TestMethod() ]
             /           \
            /             \
           /               \
      Parameters          Body   [ MethodCallExpression: c.TestMethod() ]
          |              /    \
          |             /      \
    1: MyClass c    Object [c]  \
                                /\
                               /  \
                              /    \
             Method [TestMethod]  Arguments [Empty]

您需要的是方法名称,在方法调用表达式内部,在 lambda 表达式的主体内部。所以得到这个的代码是:

static string GetInnerMethodName<T>(Expression<Action<T>> expr)
{
    MethodCallExpression mce = expr.Body as MethodCallExpression;
    return (mce != null) ? mce.Method.Name : null;
}

当然,这只有在 Expression<Action<T>> 时才有效传入的是真正的方法调用表达式;这个方法的使用者在技术上可以传入任何表达式,在这种情况下,它只会返回 null .您可以调整它以引发异常、返回默认值或执行您认为合适的任何其他操作。

你不需要做任何特别的事情来使用它 - 它的用法与你原来的方法相同:

string methodName = GetInnerMethodName<MyClass>(c => c.TestMethod());

关于c# - (Action<T>).Name 不返回预期值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2581816/

相关文章:

c# - Excel/VSTO : error 0x80028018 only when binding directly to interop. - 提供的属性

c# - Dictionary.ContainsKey/Value 和检查某个键/值的 foreach 循环之间的速度是否存在差异

c# - 已内联的函数的堆栈跟踪是否在抛出的异常中保留?

c# - 在 C# 中使用 Dictionary<T, Func<List, bool>> 查找列表中最常见的事件

ios - 无法在 Swift 的 UITextFieldDelegate 类初始值设定项中使用 TextField

c# - 将参数传递给 NUnit 测试

c# - 使用泛型转换为基类

c# - 使用 EF Core 更新通用存储库上的父集合和子集合

Swift Generics - 调用哪个方法?

ios - 为什么委托(delegate)方法可以在不声明协议(protocol)一致性的情况下工作?