![](/img/trans.png)
[英]How do you get the second item for each JSON object without using the property's name?
[英]How do you get the name of a property using the property itself
我遇到了一個問題,我需要獲取屬性的名稱以進行記錄。 我確信在 VB.Net 中有一種方法可以使用反射和 lambda 表達式的一些混合來做到這一點,但到目前為止我一直沒有成功。
我想要做的是轉換這個:
objAddress.AddressLine
對此:
"AddressLine"
過去,我使用了一種我在網上找到的方法來使用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 事件)會自動更改。
更新 (2015)
值得一提的是,Visual Studio 2015 中的新功能使這變得更加容易。 下面是上面示出的相同的代碼,但使用新的nameof
特征(其細節,以及其他新功能可以找到這里)。
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");
}
}
對於仍在尋找優雅解決方案的人,在最新版本的 VB 和 C# 中,您可以使用“nameof()”。
C#:
var propertyName = nameof(objAddress.AddressLine)
VB.NET:
Dim propertyName = nameof(objAddress.AddressLine)
請注意,如果您沒有對象的實例,則可以使用它的類名。
這將顯示當前方法。 您可能想要替換屬性名稱的“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)
來自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
我決定采用 the_lotus 對我最初使用常量的問題的回答。 如果我在不久的將來找到一種更動態的方法來做到這一點,我會嘗試發布它。 蓮花,如果你碰巧看到這個回答問題的評論,我會將回答狀態切換給你。
從 Net4.5 開始,在這種情況下使用 System.Runtime.CompilerServices 會產生奇跡。 [查看調用者信息] 可選的 CallerMemberName 字符串可用於標識調用日志的方法/屬性。
來自MSDN
Private Sub DoProcessing()
TraceMessage("Something happened.")
End Sub
Public Sub TraceMessage(message As String,
<System.Runtime.CompilerServices.CallerMemberName> Optional memberName As String = Nothing,
<System.Runtime.CompilerServices.CallerFilePath> Optional sourcefilePath As String = Nothing,
<System.Runtime.CompilerServices.CallerLineNumber()> Optional sourceLineNumber As Integer = 0)
System.Diagnostics.Trace.WriteLine("message: " & message)
System.Diagnostics.Trace.WriteLine("member name: " & memberName)
System.Diagnostics.Trace.WriteLine("source file path: " & sourcefilePath)
System.Diagnostics.Trace.WriteLine("source line number: " & sourceLineNumber)
End Sub
' Sample output:
' message: Something happened.
' member name: DoProcessing
' source file path: C:\Users\username\Documents\Visual Studio 2012\Projects\CallerInfoVB\CallerInfoVB\Form1.vb
' source line number: 15
顯示屬性調用結果的不同實現
Class Foo
Public ReadOnly Property ThisPropertyObject As Object
Get
LogManager.Ping
Return Nothing
End Get
End Property
Sub New()
Dim this = ThisPropertyObject
End Sub
End Class
Public Module LogManager
Public Sub Ping(<CallerMemberName> Optional memberName As String = Nothing,
<CallerFilePath> Optional sourcefilePath As String = Nothing,
<CallerLineNumber> Optional sourceLineNumber As Integer = 0)
Trace.Writeline(String.Format("[{0}]|{1}|LN:{2}] <PING>",
Path.GetFileName(sourcefilePath),
memberName,
sourceLineNumber)
)
)
End Sub
End Module
'! Results from 'DebugView'
' [20692][LogTestFile.vb|ThisPropertyObject|LN:62] <PING>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.