是否可以通过反射检索通过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名字。
这可能是?。
答案 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的想法,我暂时放弃了。