I'm trying to build a string for a class that contains a list of all it's property names and their respective values for that instance.
Per the question Get Property Info from an object without giving the property name as string, I'm getting the property name by using an Expression
of Type Func
Of Type T, Object
like this:
Private Function GetPropertyValuePair(Of T)(lambda As Expression(Of Func(Of T, Object))) As String
Dim body As Expression = lambda
'ensure we have the right type of thing
If TypeOf body Is LambdaExpression Then body = DirectCast(body, LambdaExpression).Body
If TypeOf body Is UnaryExpression Then body = DirectCast(body, UnaryExpression).Operand
If body.NodeType <> ExpressionType.MemberAccess Then Throw New InvalidOperationException()
'get property info
Dim memberInfo = DirectCast(body, MemberExpression).Member
Dim propInfo = DirectCast(memberInfo, PropertyInfo)
Return propInfo.Name + " - " + propInfo.GetValue(Me, Nothing)
End Function
In this manner, I'm getting the current value by taking the PropertyInfo
, and using GetValue
which searches the current instance for that property.
Then I can call it like this:
<!-- language: lang-vb -->GetPropertyValuePair(Of Foo)(Function(x) x.Bar)
Which will produce:
Bar - WhateverTheValueIsForBar
The problem is when I have is when the property is nested, GetValue
will throw the exception:
Object does not match target type.
For example, in running the following expression:
GetPropertyValuePair(Of Foo)(Function(x) x.Bar.Car)
The property info will be of of type Car
, which is not found directly on Foo
.
Can I get the instance value from the original lambda expression without having to do the search with GetValue in the first place?
This is possible with the MVC @Html.EditorFor
helper, so there must be some mechanism for delivering the value of the passed in function for something like this:
@Html.EditorFor(Function(model) model.Bar.Car)
Any Ideas?