Jak przeglądać wszystkie właściwości klasy?


168

Mam klasę.

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

Chcę przejrzeć właściwości powyższej klasy. na przykład;

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

Odpowiedzi:


297

Użyj odbicia:

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

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

dla programu Excel - jakie narzędzia / element referencyjny należy dodać, aby uzyskać dostęp do BindingFlags, ponieważ na liście nie ma wpisu „System.Reflection”

Edycja: możesz również określić wartość BindingFlags, aby type.GetProperties():

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

Spowoduje to ograniczenie zwracanych właściwości do właściwości wystąpienia publicznego (z wyłączeniem właściwości statycznych, właściwości chronionych itp.).

Nie musisz określać BindingFlags.GetProperty, używasz tego podczas wywoływania, type.InvokeMember()aby uzyskać wartość właściwości.


Przy okazji, czy nie powinno być kilku flag wiążących dla tej metody GetProperties? Jak BindingFlags.Public | BindingFlags.GetPropertyczy coś?
Svish

@Svish, masz rację :) Przydałoby się kilka BindingFlags, ale są one opcjonalne. Prawdopodobnie chcesz Public | Instancja.
Brannon

Wskazówka: jeśli masz do czynienia z polami statycznymi, po prostu podaj tutaj wartość null: property.GetValue (null);
alansiqueira27

42

Zwróć uwagę, że jeśli obiekt, o którym mówisz, ma model właściwości niestandardowych (na przykład DataRowViewitp. DataTable), Musisz użyć TypeDescriptor; dobrą wiadomością jest to, że to nadal działa dobrze na zwykłych zajęciach (i może być nawet znacznie szybsze niż refleksja ):

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

Zapewnia to również łatwy dostęp do rzeczy, takich jak TypeConverterformatowanie:

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

32

Wersja języka VB C # podana przez Brannona:

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

Używanie flag Binding zamiast linii nr 3

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

Dzięki, przejście na VB zajęłoby mi zbyt dużo czasu :)
Brannon,

zawsze możesz skorzystać z automatycznego konwertera, w sieci jest mnóstwo :)
balexandre

1
Tak, ale nie wszystko tak dobre, jak kodowanie ręczne. Godnym uwagi jest konwerter kodów telerik
Sachin Chavan

Oto, jak Telerik by się przekonwertował: gist.github.com/shmup/3f5abd617a525416fee7
shmup

7

Odbicie jest dość „ciężkie”

Być może wypróbuj to rozwiązanie: // 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

Odbicie spowalnia +/- 1000-krotność szybkości wywołania metody, pokazanej w The Performance of Everyday Things


2

Oto inny sposób, aby to zrobić, używając LINQ lambda:

DO#:

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)}"))

1

Tak to robię.

foreach (var fi in typeof(CustomRoles).GetFields())
{
    var propertyName = fi.Name;
}

1
Użyj GetProperties () zamiast GetFields (), jeśli obiekt / klasa zawiera właściwości zamiast pól.
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);
        }
    }

Użyłem powyższego bloku kodu, aby zresetować wszystkie właściwości ciągu w moim obiekcie kontroli użytkownika, którego nazwy są rozpoczynane od „Doc”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.