Expression(Of Func(Of T)).Body.Member.Name bizarre “$vb$local_” added if used inside a Property Get Accessor

♀尐吖头ヾ 提交于 2019-12-08 04:06:27

If you remember what Expressions are primarily used for, this makes sense: Expressions are generally used to compile into functions. An expression inside a Get Property that references itself would compile into an infinite loop. So instead of that lambda becoming a PropertyExpression, it becomes a FieldExpression on a closure:

GetProperty(Of Result)(Function() RegisteredServer) is the same GetProperty(Of Result)(Function() Me.RegisteredServer), so the compiler encloses the 'this' (Me) reference. A field expression around a closure can result in accessing a compiler-generated class, with weird names.

In your case, you don't really care about the 'this' reference, you just want a way to reference the Property in a strongly-typed way. You can do this by adding an explicit parameter so you're not enclosing anything:

    Public Function GetPropertyName(Of TClass, TProperty)(propertyExpression As Expression(Of Func(Of TClass, TProperty)))
        Dim memberExpr As MemberExpression = propertyExpression.Body
        If memberExpr Is Nothing Then
            Throw New ArgumentException("propertyExpression should represent access to a member")
        End If
        Dim memberName As String = memberExpr.Member.Name
        Return memberName
    End Function
    Protected Function GetProperty(Of TClass, TProperty)(propertyExpression As Expression(Of Func(Of TClass, TProperty))) As TProperty
        Dim memberName As String = GetPropertyName(propertyExpression)
        Dim value As TProperty = Nothing
        _propertyBag.TryGetValue(memberName, value)
        Return value
    End Function

... then GetProperty(Of Result)(Function() RegisteredServer) becomes GetProperty(Of YourClass, Result)(Function(c) c.RegisteredServer).


Edit: Upon further thought, you don't need the TClass type variable:

    Public Function GetPropertyName(Of T)(propertyExpression As Expression(Of Func(Of X, T)))
        Dim memberExpr As MemberExpression = propertyExpression.Body
        If memberExpr Is Nothing Then
            Throw New ArgumentException("propertyExpression should represent access to a member")
        End If
        Dim memberName As String = memberExpr.Member.Name
        Return memberName
    End Function


    Protected Function GetProperty(Of TProperty)(propertyExpression As Expression(Of Func(Of X, TProperty))) As TProperty
        Dim memberName As String = GetPropertyName(propertyExpression)
        Dim value As TProperty = Nothing
        _propertyBag.TryGetValue(memberName, value)
        Return value
    End Function

... where X is the name of your class. This means you can remove the type annotations from your GetProperty calls: So instead of GetProperty(Of Result)(Function() RegisteredServer) or GetProperty(Of YourClass, Result)(Function(c) c.RegisteredServer), you can now do: GetProperty(Function(c) c.RegisteredServer).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!