簡體   English   中英

如何遍歷一個類的所有屬性?

[英]How to loop through all the properties of a class?

我有一堂課。

Public Class Foo
    Private _Name As String
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
        End Set
    End Property

    Private _Age As String
    Public Property Age() As String
        Get
            Return _Age
        End Get
        Set(ByVal value As String)
            _Age = value
        End Set
    End Property

    Private _ContactNumber As String
    Public Property ContactNumber() As String
        Get
            Return _ContactNumber
        End Get
        Set(ByVal value As String)
            _ContactNumber = value
        End Set
    End Property


End Class

我想遍歷上述類的屬性。 例如;

Public Sub DisplayAll(ByVal Someobject As Foo)
    For Each _Property As something In Someobject.Properties
        Console.WriteLine(_Property.Name & "=" & _Property.value)
    Next
End Sub

使用反射:

Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties();

foreach (PropertyInfo property in properties)
{
    Console.WriteLine("Name: " + property.Name + ", Value: " + property.GetValue(obj, null));
}

對於 Excel - 必須添加哪些工具/參考項才能訪問 BindingFlags,因為列表中沒有“System.Reflection”條目

編輯:您還可以為type.GetProperties()指定一個 BindingFlags 值:

BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
PropertyInfo[] properties = type.GetProperties(flags);

這會將返回的屬性限制為公共實例屬性(不包括靜態屬性、受保護的屬性等)。

您不需要指定BindingFlags.GetProperty ,在調用type.InvokeMember()時使用它來獲取屬性的值。

請注意,如果您正在談論的對象具有自定義屬性模型(例如DataTableDataRowView等),那么您需要使用TypeDescriptor 好消息是這仍然適用於常規課程(甚至可以 比反射快得多):

foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) {
    Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj));
}

這也提供了對諸如TypeConverter類的內容的輕松訪問以進行格式化:

    string fmt = prop.Converter.ConvertToString(prop.GetValue(obj));

Brannon 給出的 C# 的 VB 版本:

Public Sub DisplayAll(ByVal Someobject As Foo)
    Dim _type As Type = Someobject.GetType()
    Dim properties() As PropertyInfo = _type.GetProperties()  'line 3
    For Each _property As PropertyInfo In properties
        Console.WriteLine("Name: " + _property.Name + ", Value: " + _property.GetValue(Someobject, Nothing))
    Next
End Sub

使用綁定標志代替第 3 行

    Dim flags As BindingFlags = BindingFlags.Public Or BindingFlags.Instance
    Dim properties() As PropertyInfo = _type.GetProperties(flags)

反射相當“重”

也許試試這個解決方案:

C#

if (item is IEnumerable) {
    foreach (object o in item as IEnumerable) {
            //do function
    }
} else {
    foreach (System.Reflection.PropertyInfo p in obj.GetType().GetProperties())      {
        if (p.CanRead) {
            Console.WriteLine("{0}: {1}", p.Name, p.GetValue(obj,  null)); //possible function
        }
    }
}

VB.Net

  If TypeOf item Is IEnumerable Then

    For Each o As Object In TryCast(item, IEnumerable)
               'Do Function
     Next
  Else
    For Each p As System.Reflection.PropertyInfo In obj.GetType().GetProperties()
         If p.CanRead Then
               Console.WriteLine("{0}: {1}", p.Name, p.GetValue(obj, Nothing))  'possible function
          End If
      Next
  End If

反射減慢了方法調用速度的 +/- 1000 倍,如The Performance of Everyday Things中所示

這是使用 LINQ lambda 的另一種方法:

C#:

SomeObject.GetType().GetProperties().ToList().ForEach(x => Console.WriteLine($"{x.Name} = {x.GetValue(SomeObject, null)}"));

VB.NET:

SomeObject.GetType.GetProperties.ToList.ForEach(Sub(x) Console.WriteLine($"{x.Name} = {x.GetValue(SomeObject, Nothing)}"))

我就是這樣做的。

foreach (var fi in typeof(CustomRoles).GetFields())
{
    var propertyName = fi.Name;
}
private void ResetAllProperties()
    {
        Type type = this.GetType();
        PropertyInfo[] properties = (from c in type.GetProperties()
                                     where c.Name.StartsWith("Doc")
                                     select c).ToArray();
        foreach (PropertyInfo item in properties)
        {
            if (item.PropertyType.FullName == "System.String")
                item.SetValue(this, "", null);
        }
    }

我使用上面的代碼塊來重置我的 Web 用戶控件對象中的所有字符串屬性,這些屬性的名稱以“Doc”開頭。

我使用這個例子在我的自定義文件中序列化我的數據(ini & xml mix)


' **Example of class test :**

    Imports System.Reflection
    Imports System.Text    

    Public Class Player
        Property Name As String
        Property Strong As Double
        Property Life As Integer
        Property Mana As Integer
        Property PlayerItems As List(Of PlayerItem)
    
        Sub New()
            Me.PlayerItems = New List(Of PlayerItem)
        End Sub
    
        Class PlayerItem
            Property Name As String
            Property ItemType As String
            Property ItemValue As Integer
    
            Sub New(name As String, itemtype As String, itemvalue As Integer)
                Me.Name = name
                Me.ItemType = itemtype
                Me.ItemValue = itemvalue
            End Sub
        End Class
    End Class
    
' **Loop function of properties**

    Sub ImportClass(varobject As Object)
        Dim MaVarGeneric As Object = varobject
        Dim MaVarType As Type = MaVarGeneric.GetType
        Dim MaVarProps As PropertyInfo() = MaVarType.GetProperties(BindingFlags.Public Or BindingFlags.Instance)

        Console.Write("Extract " & MaVarProps.Count & " propertie(s) from ")
        If MaVarType.DeclaringType IsNot Nothing Then
            Console.WriteLine(MaVarType.DeclaringType.ToString & "." & MaVarType.Name)
        Else
            Console.WriteLine(MaVarType.Namespace & "." & MaVarType.Name)
        End If

        For Each prop As PropertyInfo In MaVarProps
            If prop.CanRead = True Then

                If prop.GetIndexParameters().Length = 0 Then
                    Dim MaVarValue As Object = prop.GetValue(MaVarGeneric)
                    Dim MaVarValueType As Type = MaVarValue.GetType

                    If MaVarValueType.Name.Contains("List") = True Then
                        Dim MaVarArguments As New StringBuilder
                        For Each GenericParamType As Type In prop.PropertyType.GenericTypeArguments
                            If MaVarArguments.Length = 0 Then
                                MaVarArguments.Append(GenericParamType.Name)
                            Else
                                MaVarArguments.Append(", " & GenericParamType.Name)
                            End If
                        Next
                        Console.WriteLine("Sub-Extract: " & prop.MemberType.ToString & " " & prop.Name & " As List(Of " & MaVarArguments.ToString & ")")
                        Dim idxItem As Integer = 0
                        For Each ListItem As Object In MaVarValue
                            Call ImportClass(MaVarValue(idxItem))
                            idxItem += 1
                        Next
                        Continue For
                    Else
                        Console.WriteLine(prop.MemberType.ToString & " " & prop.Name & " As " & MaVarValueType.Name & " = " & prop.GetValue(varobject))
                    End If

                End If
            End If
        Next
    End Sub

' **To test it :**

        Dim newplayer As New Player With {
            .Name = "Clark Kent",
            .Strong = 5.5,
            .Life = 100,
            .Mana = 50
        }
        ' Grab a chest
        newplayer.PlayerItems.Add(New Player.PlayerItem("Chest", "Gold", 5000))
        ' Grab a potion
        newplayer.PlayerItems.Add(New Player.PlayerItem("Potion", "Life", 50))
        ' Extraction & Console output
        Call ImportClass(newplayer)

控制台中的預覽:類的屬性循環的結果

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM