jeudi 10 août 2017

Cannot get a list of properties with a shared function using reflection

This one has me foxed.

I'm using reflection in some legacy code to build a reasonable centralised Update routine in VB. We are using Linq to Sql and won't be updating this large old project to anything newer. So a halfway house is a nice datalayer to at least centralise the database access (it's a winforms old school application but using .net 4.6.1).

The code below works fine:

Public Class DataClass(Of t As Class)

Public Shared Function Update(ByRef db As DataContext,
                              UpdateItem As t,
                              originalItem As t,
                              ParamArray NonWriteable() As String) As t
    If originalItem Is Nothing OrElse UpdateItem Is Nothing Then Return Nothing
 'This is repeated in a separate clone routine.
    Dim validProperties = UpdateItem.GetType.GetProperties.Where(Function(x) Not x.PropertyType.Name.Contains("EntityRef") _
                                                             AndAlso Not NonWriteable.Contains(x.PropertyType.Name) _
                                                             AndAlso x.CanWrite AndAlso Not x.PropertyType.IsClass)
    For Each p In validProperties
        If p.PropertyType.Name.Contains("Nullable") Then
            If Not Nullable.Equals(p.GetValue(UpdateItem), p.GetValue(originalItem)) Then p.SetValue(originalItem, p.GetValue(UpdateItem))
        Else
            If p.GetValue(UpdateItem) IsNot p.GetValue(originalItem) Then p.SetValue(originalItem, p.GetValue(UpdateItem))
        End If
    Next
    If db.GetChangeSet.Updates.Count > 0 Then SubmitChanges(db)
    Return originalItem
End Function

End Class

However if I try to abstract the ValidProperties query as I use it in another clone routine, I cannot get any results from the type:

Private Shared Function _validProps(ByRef p As t, NonWriteable() As String) As List(Of PropertyInfo)
    Return p.GetType.GetProperties.Where(Function(x) x.PropertyType.Name.Contains("EntityRef") _
                                                             AndAlso Not NonWriteable.Contains(x.PropertyType.Name) _
                                                             AndAlso x.CanWrite AndAlso Not x.PropertyType.IsClass).ToList
End Function

This is how the update routine is called: Using db as new Datacontext return DataClass(Of Contact).Update(db, Updated, Original, {"contact_id", "created_on"}) end using

I'm happy to share the wider generic class for anyone else who is using DBML and can use it.

However, I definitely feel I should be able to put the more complex reflection query into it's own function, pass it a t object and get back my properties.

Any help gratefully received, though if I don't succeed it is only duplicated whenever I need these members.

Thank you!





Aucun commentaire:

Enregistrer un commentaire