0

Working with Entity Framework (EF6) and VB.Net reflection, both of which I'm not super familiar with at this point.

Here's a brief example of what I'm trying to achieve:

Dim user as New user()
user.full_name = "John Smith"

Dim str As String = "The user's name is **full_name**."

'For each p As Property In user.Properties
'    str = str.Replace("**" + p.Name + "**", p.Value)
'Next

OUTPUT: The user's name is John Smith.

However, the catch is that the object is of an anonymous type. I'd like to be able to pass in any of my entity classes and dynamically replace property occurrences.

I've tried a whole lot and read a ton of questions here on SO, but I'm still having trouble - It's quite evident that I don't properly understand reflection just yet.

I'll supply my code below, as well as anything I've referenced. If anyone can push me in the right direction, I'd be more than grateful. Thanks.


Updated per GSerg's comment:

Public Function MailMerge(htmlString As String, obj As Object) As String
    Dim keyNames As New List(Of String)

    Dim dictionaryData As New Dictionary(Of String, String)()
    For Each p As System.Reflection.PropertyInfo In obj.GetType().GetProperties()
        If p.CanRead AndAlso p.GetIndexParameters().Length = 0 Then
            Dim columnName As String = p.Name

            'FAILS HERE - p.Name is "Item" at the failing iteration
            Dim columnValue = p.GetValue(obj, Nothing)

            dictionaryData.Add(columnName, columnValue)
        End If
    Next

    For Each key In dictionaryData.Keys
        htmlString = htmlString.Replace("**" + key + "**", dictionaryData(key))
    Next

    Return htmlString

End Function

I'm only getting Capacity and Count as the properties, though given an object of type user (from above), I'd expect to have full_name.


EDIT: Turns out this function needs to handle Lists as well, which is evidently the root cause of the issue I've mentioned above. I'm going to tweak it some more and if I cannot figure it out, I'll update my question.


References:

Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
  • `Item` is the indexer, it expects a parameter. Apparently you don't want to enumerate it. – GSerg May 25 '17 at 22:20
  • So would a simple `if p.Name <> "Item"` solve my issue...? As far as I can tell, `Item` is essentially a "sibling" of the properties that I *am* trying to iterate over. Although I considered ignoring it, I didn't think that solution was too elegant - it felt like there should be a smarter way to do this without hardcoding names. – Tyler Roper May 25 '17 at 22:21
  • No, it does not have to be named `Item`. See https://stackoverflow.com/a/291380/11683. – GSerg May 25 '17 at 22:23
  • @GSerg Ah wonderful, this is a solid resource. I'll try `If p.CanRead AndAlso p.GetIndexParameters().Length = 0` and report back – Tyler Roper May 25 '17 at 22:25
  • @GSerg No more hard error, though on to the next issue. I'm only getting two non-indexer properties: `Count` and `Capacity` - am I not traversing deep enough into the object? – Tyler Roper May 25 '17 at 22:29
  • That would suggest your object is a `List` which indeed has only [two non indexer properties](https://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx#Properties), `Count` and `Capacity`... – GSerg May 25 '17 at 22:32
  • Holy crap, you're completely right - total airhead moment. Passing a `user` object would likely work, but I'm passing a `List(of user)`. If you'd like to post your suggestions here as an answer, I'd gladly mark you correct, as I can handle it from here. Otherwise, thank you and have a wonderful day/night. – Tyler Roper May 25 '17 at 22:34

0 Answers0