开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜