Wie werden alle Eigenschaften einer Klasse durchlaufen?

168

Ich habe ein klasse.

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

Ich möchte die Eigenschaften der obigen Klasse durchlaufen. z.B;

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

Antworten:

297

Reflektion verwenden:

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

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

für Excel - Welche Tools / Referenzelemente müssen hinzugefügt werden, um Zugriff auf BindingFlags zu erhalten, da die Liste keinen Eintrag "System.Reflection" enthält

Bearbeiten: Sie können auch einen BindingFlags-Wert angeben für type.GetProperties():

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

Dadurch werden die zurückgegebenen Eigenschaften auf Eigenschaften öffentlicher Instanzen beschränkt (ausgenommen statische Eigenschaften, geschützte Eigenschaften usw.).

Sie müssen nicht angeben BindingFlags.GetProperty, Sie verwenden dies beim Aufrufen type.InvokeMember(), um den Wert einer Eigenschaft abzurufen.

Brannon
quelle
Übrigens, sollte es für diese GetProperties-Methode keine Bindungsflags geben? Wie BindingFlags.Public | BindingFlags.GetPropertyoder so?
Svish
@Svish, du hast recht :) Es könnten einige BindingFlags verwendet werden, aber sie sind optional. Sie möchten wahrscheinlich Public | Beispiel.
Brannon
Tipp: Wenn Sie mit statischen Feldern arbeiten, übergeben Sie hier einfach null: property.GetValue (null);
Alansiqueira27
42

Beachten Sie, dass Sie verwenden müssen, wenn das Objekt, über das Sie sprechen, ein benutzerdefiniertes Eigenschaftsmodell hat (z. B. DataRowViewusw. für DataTable) TypeDescriptor. Die gute Nachricht ist, dass dies für den regulären Unterricht immer noch gut funktioniert (und sogar viel schneller als das Nachdenken sein kann ):

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

Dies bietet auch einfachen Zugriff auf Dinge wie TypeConverterzum Formatieren:

    string fmt = prop.Converter.ConvertToString(prop.GetValue(obj));
Marc Gravell
quelle
32

VB-Version von C # von Brannon:

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

Verwenden von Bindungsflags anstelle von Zeile Nr. 3

    Dim flags As BindingFlags = BindingFlags.Public Or BindingFlags.Instance
    Dim properties() As PropertyInfo = _type.GetProperties(flags)
Sachin Chavan
quelle
Danke, ich hätte zu lange gebraucht, um zu VB zu konvertieren :)
Brannon
Sie können immer einen automatischen Konverter verwenden, es gibt viele im Web :)
Balexandre
1
Ja, aber nicht alle so gut wie Handcodierung. Eine bemerkenswerte ist Telerik Code Converter
Sachin Chavan
So hätte Telerik konvertiert: gist.github.com/shmup/3f5abd617a525416fee7
shmup
7

Reflexion ist ziemlich "schwer"

Versuchen Sie vielleicht diese Lösung: // 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

Die Reflexion verlangsamt das +/- 1000-fache der Geschwindigkeit eines Methodenaufrufs, wie in Die Leistung alltäglicher Dinge gezeigt

NicoJuicy
quelle
2

Hier ist eine andere Möglichkeit, dies mit einem LINQ-Lambda zu tun:

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)}"))
01F0
quelle
1

So mache ich es.

foreach (var fi in typeof(CustomRoles).GetFields())
{
    var propertyName = fi.Name;
}
Chris Go
quelle
1
Verwenden Sie GetProperties () anstelle von GetFields (), wenn das Objekt / die Klasse Eigenschaften anstelle von Feldern enthält.
GarDavis
0
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);
        }
    }

Ich habe den obigen Codeblock verwendet, um alle Zeichenfolgeneigenschaften in meinem Webbenutzersteuerungsobjekt zurückzusetzen, deren Namen mit "Doc" gestartet werden.

Jack
quelle