获取通过lambda表达式传递的方法名称?

时间:2015-06-16 20:57:32

标签: .net vb.net reflection delegates pinvoke

是否可以通过反射检索通过lambda表达式传递的真实方法名称?

我想平台调用一些具有更好错误处理功能的函数,然后为了避免重复大量Marshal.GetLastWin32Error条件,我想在创建一个通用方法来自动化它,我传递一个引用对象和一个lambda表达式:

<DebuggerStepThrough>
Private Shared Sub SafePInvoke(Of T)(ByRef resultVar As T, ByVal [function] As Func(Of T))

    resultVar = [function].Invoke

    Dim lastError As Integer = Marshal.GetLastWin32Error

    If lastError <> 0 Then
        Throw New Win32Exception([error]:=lastError, message:=String.Format("Function '{0}' thrown an unhandled Win32 exception with error code '{1}'.",
                                                                            [function].Method.Name, CStr(lastError)))
    End If

End Sub

然后,我可以这样做来简化错误处理:

Dim length As Integer
SafePInvoke(length, Function() NativeMethods.GetWindowTextLength(hWnd))

我不知道它是否可以进一步改进,知道它会很棒。

嗯,现在,只是为了美学的事情,如果函数得到一个win32错误我抛出异常并在异常消息中我想显示真正的方法名称,在这种情况下GetWindowTextLength而不是“匿名”lambda名字。

这可能是?。

1 个答案:

答案 0 :(得分:2)

我不会这样做。传递表示要显示的错误消息的字符串var或其中的一部分(如函数名称)会更简单。

“最简单”的方式是使用Expression Tree。为此,您需要更改SafePInvoke的签名以接受Expression

使用它可以编译表达式,并调用它来执行PInvoke。如果出现错误,请使用表达式树获取名称:

Imports System.Linq.Expressions
...
Private Shared Sub SafePInvoke(Of T)(ByRef result As T, expr As Expression(Of Func(Of T)))
    ' compile the function and invoke it
    Dim result = expr.Compile.Invoke()

    Dim lastError As Integer = Marshal.GetLastWin32Error

    If lastError <> 0 Then
        ' this is easy, but it is the full signature w/ params
        'Dim name = expr.Body.ToString

        ' ToDo: add try Catch
        Dim MethName = CType(expr.Body, MethodCallExpression).Method.Name

        Dim errMsg = MethName & " failed"
    End If
End Sub

为了获得这个名字而铸造它是Sehnsucht的想法,我暂时放弃了。

相关问题