2013-11-14 4 views
3

У меня возникла проблема, когда мне нужно получить имя свойства для ведения журнала. Я уверен, что есть способ сделать это в VB.Net, используя некоторую амальгаму отражений и лямбда-выражений, но до сих пор я не увенчался успехом.Как получить имя свойства с использованием самого свойства

То, что я пытаюсь сделать, это преобразовать это:

objAddress.AddressLine 

к этому:

"AddressLine" 
+0

Откуда вы знаете, что это свойство objAddress.AddressLine, которое вам нужно? Если это всегда одно и то же свойство, вы можете просто добавить константу в класс ex: ADDRESSLINE_PROPERTYNAME = "AddressLine" –

+0

Это правда. Я надеялся обеспечить, чтобы этот журнал всегда оставался динамичным, если другие программисты в моей команде не нуждались в знаниях, чтобы изменить функцию ведения журнала, если они по каким-либо причинам меняют свойство (что было бы нарушением принципа Open/Closed, но другие программисты в моей команде не следуют правилам SOLID). – Lykeuhfox

+0

, если вы не можете найти динамический способ, обязательно напишите комментарии к свойству: «Если вы измените имя, не забудьте изменить константу». –

ответ

5

В прошлом я использовал метод, который я нашел в Интернете для этого с помощью INotifyPropertyChanged. Я не могу вспомнить, где именно, но это детали такое же разрешение:

http://paulstovell.com/blog/strong-property-names

C#

public class Test : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private string _Name; 

    public string Name 
    { 
     get { return _Name; } 
     set 
     { 
      _Name = value; 
      RaisePropertyChanged(() => Name); 
     } 
    } 

    private void RaisePropertyChanged(Expression<Func<object>> property) 
    { 
     MemberExpression exp = property.Body as MemberExpression; 

     if (exp != null) 
     { 
       PropertyChanged(this, new PropertyChangedEventArgs(exp.Member.Name)); 
     } 
    } 


} 

VB

Public Class Test 
    Implements INotifyPropertyChanged 

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged 
    Private _Name As String 

    Public Property Name() As String 
     Get 
      Return _Name 
     End Get 
     Set(value As String) 
      _Name = value 
      RaisePropertyChanged(Function() Me.Name) 
     End Set 
    End Property 

    Private Sub RaisePropertyChanged(Of T)(propertyName As Expression(Of Func(Of T))) 
     Dim exp As MemberExpression = TryCast(propertyName.Body, MemberExpression) 

     If exp IsNot Nothing Then 
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(exp.Member.Name)) 
     End If 
    End Sub 



End Class 

Главное преимущество делать это является рефакторинг. Если я когда-либо переименовал свое свойство, событие Lambda (и расширение NotifyPropertyChanged) автоматически изменится.


Update (2015)

Может быть, стоит отметить, что новые функции в Visual Studio 2015 сделать это еще проще. Ниже приведен код, приведенный выше, но с использованием новой функции nameof (подробности об этом и других новых функциях можно найти Here).

C#

public class Test : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    string _Name; 

    public string Name 
    { 
     get { return _Name; } 
     set 
     { 
      _Name = value; 
      RaisePropertyChanged(nameof(Name)); 
     } 
    } 

    private void RaisePropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 
} 

VB

Public Class Test 
    Implements INotifyPropertyChanged 

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged 
    Private _Name As String 

    Public Property Name() As String 
     Get 
      Return _Name 
     End Get 
     Set(value As String) 
      _Name = value 
      RaisePropertyChanged(NameOf(Name)) 
     End Set 
    End Property 

    Private Sub RaisePropertyChanged(propertyName As String) 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
    End Sub 

End Class 

Вы можете даже использовать nameof на стороне абонента, для того, чтобы определить, является ли свойство является один вы заботитесь о:

private static void PropChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == nameof(Test.Name)) 
     { 
      Console.WriteLine("The Property I care about changed"); 
     } 
    } 
0

От MSDN

Imports System 
Imports System.Reflection 
Class MyClass1 
    Private myProperty1 As Integer 
    ' Declare MyProperty. 

    Public Property MyProperty() As Integer 
     Get 
      Return myProperty1 
     End Get 
     Set(ByVal Value As Integer) 
      myProperty1 = Value 
     End Set 
    End Property 
End Class 'MyClass1 

Public Class MyTypeClass 
    Public Shared Sub Main(ByVal args() As String) 
     Try 
      ' Get Type Object corresponding to MyClass. 
      Dim myType As Type = GetType(MyClass1) 
      ' Get PropertyInfo object by passing property name. 
      Dim myPropInfo As PropertyInfo = myType.GetProperty("MyProperty") 
      ' Display Name propety to console. 
      Console.WriteLine("The {0} property exists in MyClass.", myPropInfo.Name) 
     Catch e As NullReferenceException 
      Console.WriteLine("The property does not exist in MyClass.", e.Message.ToString()) 
     End Try 
    End Sub 'Main 
End Class 'MyTypeClass 
2

Это покажет текущий метод. Возможно, вы захотите заменить префикс «get_» имени свойства.

Public Class People 
    Public Shared ReadOnly Property Address As String 
     Get 
      Return System.Reflection.MethodInfo.GetCurrentMethod().ToString() 
     End Get 
    End Property 
End Class 

' print it 
System.Diagnostics.Debug.Print(People.Address) 
0

Я решил пойти с ответом the_lotus на мой первоначальный вопрос, который должен был использовать константу. Если я найду более динамичный способ сделать это в ближайшем будущем, я постараюсь опубликовать его. лотос, если вам удастся ответить на этот вопрос с вашим комментарием, я переключу ответный статус на вас.

4

Для тех, кто все еще ищет элегантное решение, в последней версии VB и C# вы можете использовать «nameof()».

C#:

var propertyName = nameof(objAddress.AddressLine) 

VB .NET:

Dim propertyName = nameof(objAddress.AddressLine) 

Обратите внимание, что если у вас нет экземпляра объекта, который вы можете просто использовать это имя класса.

Смежные вопросы