Дай мне свое имя, я призову тебя

Эта общая функция вызывает свойство данного объекта по имени:

  Private Shared Function GetPropertyValueByName(Of TObject, TProperty)(
        ByVal T As TObject,
        ByVal PropertyName As String) As TProperty

        Dim result = GetType(TObject).GetProperties() _
            .Where(
                Function(p) (p.Name = PropertyName) _
                    AndAlso p.CanRead() _
                    AndAlso (p.PropertyType Is GetType(TProperty))
                ).FirstOrDefault()

        If (result IsNot Nothing) Then
            Return CType(result.GetValue(T), TProperty)
        End If

        Return Nothing

    End Function

Можно ли каким-то образом улучшить эту функцию? Может ли он генерировать какие-то проблемы, о которых я должен знать? Могут ли быть улучшены с точки зрения удобочитаемости?

11 голосов | спросил Francesco Bonizzi 21 MonEurope/Moscow2015-12-21T16:30:18+03:00Europe/Moscow12bEurope/MoscowMon, 21 Dec 2015 16:30:18 +0300 2015, 16:30:18

3 ответа


4

Обычно для доступа к одному конкретному свойству (а не перечислению всех как это сделано для, например, представление свойств конструктора форм), вы не использовали бы GetProperties. Поэтому мы можем упростить код:

Private Shared Function GetPropertyValueByName(Of TObject, TProperty) (
    ByVal T As TObject,
    ByVal PropertyName As String) As TProperty

    Dim result = GetType(TObject).GetProperty(PropertyName, GetType(Property), {})

    If (result IsNot Nothing) Then
        Return CType(result.GetValue(T), TProperty)
    End If

    Return Nothing

End Function

Так как типы CLI могут иметь только одно свойство с заданным именем (вы не можете имеют несколько свойств, перегруженных возвращаемым типом), вы можете упростить это если вы согласны с тем, что вы можете получить другой тип, а затем переведите его в тип TProperty.

Private Shared Function GetPropertyValueByName(Of TObject, TProperty) (
    ByVal T As TObject,
    ByVal PropertyName As String) As TProperty

    Const flag = BindingFlags.Public Or BindingFlags.Instance or BindingFlags.GetProperty
    Dim value = GetType(TObject).InvokeMember(PropertyName, flag, Nothing, T, {})
    Return CType(value, TProperty)
End Function

Если вы хотите вернуть Nothing, если свойство не найдено или имеет неправильное значение тип, вам нужно будет ловить исключения.

Вы также можете избежать передачи в TObject, просто используя метод .GetType(), но это еще больше изменяет семантику.

ПРИМЕЧАНИЕ. Прошло некоторое время с тех пор, как я закодирован в VB, и я не уверен на 100%, что {} правильный синтаксис для пустого массива, тип которого может быть выведен. Он предназначен как пустой массив типа в первом примере, а Object - во втором примере.

ответил Random832 22 TueEurope/Moscow2015-12-22T07:14:07+03:00Europe/Moscow12bEurope/MoscowTue, 22 Dec 2015 07:14:07 +0300 2015, 07:14:07
9

LINQ предлагает два синтаксиса. Вы использовали синтаксис метода , который я считаю очень аккуратным и полезным, но для более простых запросов я нахожу, что синтаксис выглядит гораздо менее громоздким в VB.NET:

Dim result = (From p In GetType(TObject).GetProperties()
              Where p.Name = PropertyName _
                  AndAlso p.CanRead() _
                  AndAlso p.PropertyType Is GetType(TProperty)
              Select p) _
             .FirstOrDefault()

Он удаляет объявление анонимной функции inline Function(p) и оставляет его компилятору для его создания, что по очереди освобождает ваш код от некоторых шаблонов.

ответил Mathieu Guindon 21 MonEurope/Moscow2015-12-21T18:14:42+03:00Europe/Moscow12bEurope/MoscowMon, 21 Dec 2015 18:14:42 +0300 2015, 18:14:42
5
  

«Может ли он генерировать какие-то проблемы, о которых я должен знать?»

Да, он выкинет TargetParameterCountException , если свойство содержит параметры, поэтому вы можете добавить следующую строку в предикат Where.

AndAlso (p.GetIndexParameters().Length = 0)

Это приведет к исключению свойств, подобных приведенным ниже.

Public Property Pixel(x As Int32, y As Int32) As Color
ответил Bjørn-Roger Kringsjå 21 MonEurope/Moscow2015-12-21T19:21:32+03:00Europe/Moscow12bEurope/MoscowMon, 21 Dec 2015 19:21:32 +0300 2015, 19:21:32

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132