是否有一种在C#中声明方法名称的类型方式

wls*_*ill 2 .net c# reflection

我有一些反射代码,我希望有一种方法将方法名称绑定到类型而不是通过字符串声明.

我有这个界面:

interface IDoStuff<T> {
    void Do(T stuff);
}
Run Code Online (Sandbox Code Playgroud)

然后我有这个代码:

object stuff = GotThisFromSomewhereElse();
object doer = GotThisFromSomewhereElseAlso();
var doMethodInfo = doer.GetType().GetMethod("Do");
doMethodInfo.Invoke(doer, new[] { stuff });
Run Code Online (Sandbox Code Playgroud)

问题是我不能简单地进行安全演员并调用它,因为它是通用的,我实际上并不知道T是什么类型.

这工作正常,但是当我重命名方法时,我必须更新它,我并不过分担心,因为我有测试来确认所有这些工作,以防止不知道它改变.

它真的很丑陋,我很好奇是否有一些光滑的方式来进行这种打字,因此如果我改变它将由ReSharper重命名.

我真的很喜欢这样的东西:

object stuff = GotThisFromSomewhereElse();
object doer = GotThisFromSomewhereElseAlso();
var doMethodInfo = doer.GetType().Methods.Do;
doMethodInfo.Invoke(doer, new[] { stuff });
Run Code Online (Sandbox Code Playgroud)

在此先感谢,如果这是C#中可能的事情,请告诉我.

sst*_*tan 7

从C#6开始,您将能够使用新的nameof语句来避免魔术字符串:

IDoStuff<object> dummy = null; // don't need a valid instance.
string methodName = nameof(dummy.Do) // yay! no magic strings.
Run Code Online (Sandbox Code Playgroud)

编辑: @ 31eee384在评论中指出,上述内容可以进一步简化如下:

string methodName = nameof(IDoStuff<object>.Do);
Run Code Online (Sandbox Code Playgroud)

关于新的nameof声明,文档可以说,这看起来非常符合OP试图完成的内容:

您经常要捕获方法的字符串名称.使用nameof有助于在重命名定义时保持代码有效.之前必须使用字符串文字来引用定义,这在重命名代码元素时很脆弱,因为工具不知道检查这些字符串文字.


在C#6之前,也可以通过使用表达式来避免魔术字符串,但它有点笨拙.这是一个适用于您的案例的示例.

首先,编写以下扩展方法:

public static string GetMethodName<T>(this T instance, Expression<Action<T>> methodExpression)
{
    if (methodExpression.Body is MethodCallExpression)
    {
        return ((MethodCallExpression)methodExpression.Body).Method.Name;
    }
    else
    {
        throw new ArgumentException(string.Format("Invalid method expression: {0}", methodExpression.Body));
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

IDoStuff<object> dummy = null; // don't need a valid instance.
string methodName = dummy.GetMethodName(t => t.Do(null)); // yay! still no magic strings.
Run Code Online (Sandbox Code Playgroud)