C#(.NET 3.5)有没有办法获得这个函数名?

时间:2009-12-03 18:49:31

标签: c# .net lambda

我有一个函数可以调用我的一个套接字类型。如果有错误,我希望能够打印警告并重试。在警告中,我想要方法名称。然而,它被宣布为lambda。这甚至可能吗?

我如何调用函数(假设函数名为myMain):

SafeSocketCommand(() => this.mySocket.ReadCurrentBuffer());

基本包装功能:

protected TResult SafeSocketCommand<TResult>(Func<TResult> socketCommand)
{
    TResult retValue = default(TResult);
    try
    {
        retValue = socketCommand();
    }
    catch (PacketLost)
    {
        ReportToLogs("Timeout on command '" + socketCommand.Method.Name);
    }
    return retValue;
}

但是socketCommand.Method.Name给了我调用方法(来自Stack Trace?)'&lt; myMain&gt; b__3'我希望socketCommand(mySocket.ReadCurrentBuffer)调用实际函数。是否有可能在任何地方获取此信息,或者由于在lambda中声明而丢失?

编辑:

我应该提到我使用这个特殊的调用约定,以便我可以使用各种签名的基于套接字的命令。

int i = SafeSocketCommand(() => this.mySocket.FunctionReturnsInt())
bool b = SafeSocketCommand(() => this.mySocket.FunctionReturnsBool(string s))
object o = SafeSocketCommand(() => this.mySocket.Complicated(string s, int i, bool b))

它还通过重载处理没有返回类型的签名:

protected void SafeSocketCommand(Action socketCommand)
{
    SafeSocketCommand(() => { socketCommand(); return 0; });
}

4 个答案:

答案 0 :(得分:5)

如果您修改SafeSocketCommand以接受Expression<Func<TResult>>,那么您将可以访问表示lambda正文的表达式树,您可以从中访问ReadCurrentBuffer调用直接

但是,如果你这样做,你将不再处理常规的匿名方法;要实际调用它,您需要将表达式树编译为代码。您可能还需要灵活处理代码期望在lambda体内出现的内容。

答案 1 :(得分:2)

不,因为lambda没有名字;他们是匿名的功能。但是,您可以从最后一个堆栈框架中获取方法名称:

new StackFrame(1).GetMethod().Name;

答案 2 :(得分:2)

Func<TResult>只是一名代表。而不是使用lambda,创建一个匹配Func<TResult>的签名并调用它的方法。这样,你就可以得到你想要的任何名字。

SafeSocketCommand(MyNewMethod);

...

public TResult MyNewMethod()
{
    return this.mySocket.ReadCurrentBuffer();
}

答案 3 :(得分:0)

在这种情况下,您可以简单地调用此调用。它也会更快,更小的生成代码。

SafeSocketCommand(mySocket.ReadCurrentBuffer);

通常,Exception对象的StackTrace包含您要查找的完整信息,很多比打印方法名称更准确,或者您可以使用{{3} }属性,用于抛出异常的方法的名称。