Como percorrer todas as propriedades de uma classe?


168

Eu tenho aula

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

Eu quero percorrer as propriedades da classe acima. por exemplo;

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

Respostas:


297

Use a reflexão:

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

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

para Excel - que ferramentas / item de referência devem ser adicionados para obter acesso a BindingFlags, pois não há entrada "System.Reflection" na lista

Editar: Você também pode especificar um valor BindingFlags para type.GetProperties():

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

Isso restringirá as propriedades retornadas às propriedades da instância pública (excluindo propriedades estáticas, protegidas etc.).

Você não precisa especificar BindingFlags.GetProperty, usa isso ao chamar type.InvokeMember()para obter o valor de uma propriedade.


Btw, não deveria haver alguns sinalizadores de ligação para esse método GetProperties? Gosta BindingFlags.Public | BindingFlags.GetPropertyou algo assim?
Svish

@ Skish, você está certo :) Poderia usar alguns BindingFlags, mas eles são opcionais. Você provavelmente quer Público | Instância.
10119 Brannon

Dica: Se você estiver lidando com campos estáticos, simplesmente passe nulo aqui: property.GetValue (null);
precisa saber é o seguinte

42

Observe que, se o objeto que você está falando tiver um modelo de propriedade personalizado (como DataRowViewetc para DataTable), será necessário usar TypeDescriptor; a boa notícia é que isso ainda funciona bem para aulas regulares (e pode até ser muito mais rápido que a reflexão ):

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

Isso também fornece acesso fácil a coisas como TypeConverterformatação:

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

32

Versão VB do C # fornecida por 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

Usando sinalizadores Binding no lugar da linha no.3

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

Graças, teria me levado muito tempo para converter em VB :)
Brannon

você sempre pode usar um conversor automático, há uma abundância na web :)
balexandre

1
Sim, mas não tão bom quanto a codificação manual. Um um notável é conversor de código telerik
Sachin Chavan

Aqui está como a Telerik teria se convertido: gist.github.com/shmup/3f5abd617a525416fee7
shmup

7

A reflexão é bastante "pesada"

Talvez tente esta solução: // 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

A reflexão diminui +/- 1000 x a velocidade de uma chamada de método, mostrada em O desempenho das coisas cotidianas


2

Aqui está outra maneira de fazer isso, usando uma lambda LINQ:

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

1

É assim que eu faço.

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

1
Use GetProperties () em vez de GetFields () se o objeto / classe contiver propriedades em vez de campos.
21419 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);
        }
    }

Eu usei o bloco de código acima para redefinir todas as propriedades de string no meu objeto de controle de usuário da web cujos nomes são iniciados com "Doc".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.