vb.net 如何使用属性本身获取属性的名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19981086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 15:49:29  来源:igfitidea点击:

How do you get the name of a property using the property itself

vb.netreflectionpropertieslambda

提问by Lykeuhfox

I've run into an issue where I need to get the name of a property for logging purposes. I'm sure there is a way to do this in VB.Net using some amalgam of reflection and lambda expressions, but I've been unsuccessful so far.

我遇到了一个问题,我需要获取属性的名称以进行记录。我确信在 VB.Net 中有一种方法可以使用反射和 lambda 表达式的一些混合来做到这一点,但到目前为止我一直没有成功。

What I'm trying to do is convert this:

我想要做的是转换这个:

objAddress.AddressLine

to this:

对此:

"AddressLine"

回答by Obsidian Phoenix

In the past, I've used a method I found online for doing this with INotifyPropertyChanged. I can't remember exactly where, but this details the same resolution:

过去,我使用了一种在网上找到的方法来使用INotifyPropertyChanged. 我不记得确切的位置,但这详细说明了相同的分辨率:

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

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

C#

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

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

The main benefit of doing this is refactoring. If I ever rename my property, the Lambda (and by extension NotifyPropertyChanged event) changes automatically.

这样做的主要好处是重构。如果我重命名我的属性,Lambda(以及扩展 NotifyPropertyChanged 事件)会自动更改。



Update (2015)

更新 (2015)

It may be worth mentioning that the new features in Visual Studio 2015 make this even easier. Below is the same code shown above, but using the new nameoffeature (Details of this, and of other new features can be found Here).

值得一提的是,Visual Studio 2015 中的新功能使这变得更加容易。下面是上面显示的相同代码,但使用了新nameof功能(可以在此处找到有关此和其他新功能的详细信息)。

C#

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

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

You can even use nameofon the subscriber side, in order to determine if the property is the one you care about:

您甚至可以nameof在订阅者端使用,以确定该属性是否是您关心的:

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

回答by Stefan Vasiljevic

For someone who is still looking for an elegant solution, in the latest version of VB and C# you can use "nameof()".

对于仍在寻找优雅解决方案的人,在最新版本的 VB 和 C# 中,您可以使用“nameof()”。

C#:

C#:

var propertyName = nameof(objAddress.AddressLine)

VB .NET:

VB.NET:

Dim propertyName = nameof(objAddress.AddressLine)

Note that if you do not have an instance of an object you can just use it's class name.

请注意,如果您没有对象的实例,则可以仅使用它的类名。

回答by laylarenee

This will show the current Method. You may want to replace the "get_" prefix of the property name.

这将显示当前方法。您可能想要替换属性名称的“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)

回答by Lykeuhfox

I decided to go with the_lotus's response to my initial question which was to use a constant. If I find a more dynamic way to do this in the near future I'll try to post it. lotus, if you happen to see this an answer the question with your comment, i'll switch the answered status over to you.

我决定采用 the_lotus 对我最初使用常量的问题的回答。如果我在不久的将来找到一种更动态的方法来做到这一点,我会尝试发布它。莲花,如果您碰巧看到此问题并通过您的评论回答问题,我会将回答状态切换给您。

回答by Babblo

From MSDN

来自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 

回答by Crab Apple

Using the System.Runtime.CompilerServices works wonders in this case, as of Net4.5. [See Caller Information] The optional CallerMemberName string can be used to identify what method/property called the log.

从 Net4.5 开始,在这种情况下使用 System.Runtime.CompilerServices 会产生奇迹。[查看调用者信息] 可选的 CallerMemberName 字符串可用于标识调用日志的方法/属性。

From MSDN

来自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


Different implementation showing results from a Property Call

显示属性调用结果的不同实现

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>