Pass property to access using .NET
I'm fairly sure this is possible, but what I want to do is have a generic method where I can pass in an object along with a Expression that will tell the method which Property to use in it's logic.
Can anyone get me started on the syntax for something like this?
Essentially what I would like to code is something like:
Dim firstNameMapper as IColumnMapper = new ColumnMapper(of Author)(Function(x) x.FirstName)
Dim someAuthorObject as new Author()
fistNameMapper.Map("Richard", someAuthorObject)
Now the mapper object would kno开发者_运维百科w to set the FirstName property to "Richard".
Now using a Function here won't work, I know this... I'm just trying to give an idea what I'm trying to work towards.
Thanks for any help!
You could use expression trees to implement this behavior, but it would be a lot simpler to pass the ColumnMapper
a slightly different function. Instead of using expression that reads the property, you could give it a function that sets the value of the property:
Dim firstNameMapper as IColumnMapper = _
new ColumnMapper(of Author)(Sub(x, newValue) _
x.FirstName = newValue _
End Sub)
I think this syntax is new in Visual Studio 2010 (but I'm not a VB expert). Anyway, the type of the parameter would be Action<Author, string>
and you could simply invoke it anytime you needed from the ColumnMapper
to set the property.
Using expression trees, you'd have to construct expression that sets the property and compile it at runtime, so I think the additional few bits of code above are easier way to solve the problem.
Okay, so I have implemented an analogous solution (i'm not using 2010 so I can't use Tomas' solution directly) but although it compiles, the property does not seem to be set. So here are all the pieces:
Module Module1
Sub Main()
Dim inputSource() As String = {"Richard", "Dawkins"}
Dim firstNameMapper As New ColumnMapper(Of Author)(Function(obj, value) obj.FirstName = value, 0)
Dim lastNameMapper As New ColumnMapper(Of Author)(Function(obj, value) obj.LastName = value, 1)
Dim theAuthor As New Author
firstNameMapper.map(inputSource, theAuthor)
lastNameMapper.map(inputSource, theAuthor)
System.Console.WriteLine(theAuthor.FirstName + " " + theAuthor.LastName)
System.Console.ReadLine()
End Sub
End Module
Public Class ColumnMapper(Of T As {Class})
Dim _propertyMapper As Action(Of T, String)
Dim _columnIndex As Int32
Public Sub New(ByVal mapAction As Action(Of T, String), ByVal columnNumber As Int32)
_propertyMapper = mapAction
_columnIndex = columnNumber
End Sub
Public Sub map(ByVal sourceFields As String(), ByRef destinationObject As T)
_propertyMapper(destinationObject, sourceFields(_columnIndex))
End Sub
End Class
Public Class Author
Private _firstName As String
Private _lastName As String
Public Property FirstName() As String
Get
Return _firstName
End Get
Set (ByVal value As String)
_firstName = value
End Set
End Property
Public Property LastName() As String
Get
Return _lastName
End Get
Set (ByVal value As String)
_lastName = value
End Set
End Property
End Class
Any idea why the property is not being set?
Not sure why the solution using inline 'Function' doesn't work. Perhaps someone more versed in the inner workings of vb.net can explain it, but if you implement the main module as below, it works. Thanks Tomas for pointing me in the right direction!
Module Module1
Sub Main()
Dim mapAction As Action(Of Author, String)
Dim inputSource() As String = {"Richard", "Dawkins"}
Dim firstNameMapper As New ColumnMapper(Of Author)(AddressOf setFirstName, 0)
Dim lastNameMapper As New ColumnMapper(Of Author)(AddressOf setLastName, 1)
Dim theAuthor As New Author
firstNameMapper.map(inputSource, theAuthor)
lastNameMapper.map(inputSource, theAuthor)
System.Console.WriteLine(theAuthor.FirstName + " " + theAuthor.LastName)
System.Console.ReadLine()
End Sub
Public Sub setFirstName(ByVal obj As Author, ByVal value As String)
obj.FirstName = value
End Sub
Public Sub setLastName(ByVal obj As Author, ByVal value As String)
obj.LastName = value
End Sub
End Module
精彩评论