Como obter uma propriedade estática com reflexão


109

Isso parece muito básico, mas não consigo fazer funcionar. Eu tenho um objeto e estou usando reflexão para chegar às suas propriedades públicas. Uma dessas propriedades é estática e não estou tendo sorte em chegar a ela.

Public Function GetProp(ByRef obj As Object, ByVal propName as String) as PropertyInfo
    Return obj.GetType.GetProperty(propName)

End Function

O código acima funciona bem para propriedades de instância pública, que até agora é tudo o que eu precisava. Supostamente, posso usar BindingFlags para solicitar outros tipos de propriedades (privadas, estáticas), mas não consigo encontrar a combinação certa.

Public Function GetProp(ByRef obj As Object, ByVal propName as String) as PropertyInfo
    Return obj.GetType.GetProperty(propName, Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public)

End Function

Mesmo assim, solicitar qualquer membro estático não retornará nada. O refletor .NET pode ver as propriedades estáticas perfeitamente, então é claro que estou perdendo algo aqui.


Isso é muito, muito semelhante a isto: stackoverflow.com/questions/392122/…
ctacke

Bem, é semelhante porque ambos usam BindingFlags. Estou procurando uma combinação específica de BindingFlags que me permitirá obter membros públicos, sejam eles estáticos ou de instância.
Corey Downie

Respostas:


129

Ou apenas olhe isso ...

Type type = typeof(MyClass); // MyClass is static class with static properties
foreach (var p in type.GetProperties())
{
   var v = p.GetValue(null, null); // static classes cannot be instanced, so use null...
}

2
A quais variáveis ​​esses dois nulos correspondem? Como você escreveria isso usando argumentos nomeados, se possível? Obrigado.
Hamish Grubijan

Para classe estática interna?
Kiquenet

Esta é a melhor opção, na minha opinião deve ser selecionada como resposta.
c0y0teX de

8
p.GetValue(null);funciona também. O segundo nullnão é obrigatório.
Crono de

Parece ótimo. O objetivo era obter a propriedade com base em um argumento de nome - não acho que gostaria de fazer um loop em todas as propriedades para conseguir isso.
Corey Downie

42

Isso é C #, mas deve lhe dar uma ideia:

public static void Main() {
    typeof(Program).GetProperty("GetMe", BindingFlags.NonPublic | BindingFlags.Static);
}

private static int GetMe {
    get { return 0; }
}

(você precisa OR não público e estático apenas)


3
No meu caso, usar apenas esses dois sinalizadores não funcionou. Também tive que usar o sinalizador .FlattenHierarchy.
Corey Downie

3
@CoreyDownie concordou. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchyfoi a única coisa que funcionou para mim.
Jonathon Reinhart

40

Um pouco de clareza ...

// Get a PropertyInfo of specific property type(T).GetProperty(....)
PropertyInfo propertyInfo;
propertyInfo = typeof(TypeWithTheStaticProperty)
    .GetProperty("NameOfStaticProperty", BindingFlags.Public | BindingFlags.Static); 

// Use the PropertyInfo to retrieve the value from the type by not passing in an instance
object value = propertyInfo.GetValue(null, null);

// Cast the value to the desired type
ExpectedType typedValue = (ExpectedType) value;

1
BindingFlags.Instance | BindingFlags.Staticresolveu para mim.
LosManos

28

Ok, então a chave para mim era usar o .FlattenHierarchy BindingFlag. Eu realmente não sei por que eu apenas adicionei por um palpite e começou a funcionar. Portanto, a solução final que me permite obter uma instância pública ou propriedades estáticas é:

obj.GetType.GetProperty(propName, Reflection.BindingFlags.Public _
  Or Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or _
  Reflection.BindingFlags.FlattenHierarchy)

7
myType.GetProperties(BindingFlags.Public | BindingFlags.Static |  BindingFlags.FlattenHierarchy);

Isso retornará todas as propriedades estáticas na classe base estática ou um tipo específico e provavelmente o filho também.


2

Só queria esclarecer isso para mim, ao usar a nova API de reflexão baseada em TypeInfo- onde BindingFlagsnão está disponível de forma confiável (dependendo da estrutura de destino).

No 'novo' reflexo, para obter as propriedades estáticas de um tipo (não incluindo a (s) classe (s) base), você deve fazer algo como:

IEnumerable<PropertyInfo> props = 
  type.GetTypeInfo().DeclaredProperties.Where(p => 
    (p.GetMethod != null && p.GetMethod.IsStatic) ||
    (p.SetMethod != null && p.SetMethod.IsStatic));

Atende propriedades somente leitura ou somente gravação (apesar de somente gravação ser uma ideia terrível).

O DeclaredPropertiesmembro também não distingue entre propriedades com acessores públicos / privados - portanto, para filtrar a visibilidade, você precisa fazer isso com base no acessador que precisa usar. Por exemplo, supondo que a chamada acima tenha retornado, você pode fazer:

var publicStaticReadable = props.Where(p => p.GetMethod != null && p.GetMethod.IsPublic);

Existem alguns métodos de atalho disponíveis - mas, no final das contas, todos nós iremos escrever muito mais métodos de extensão em torno dos TypeInfométodos / propriedades de consulta no futuro. Além disso, a nova API nos força a pensar exatamente no que consideramos uma propriedade 'privada' ou 'pública' a partir de agora - porque devemos nos filtrar com base em acessadores individuais.


1

O abaixo parece funcionar para mim.

using System;
using System.Reflection;

public class ReflectStatic
{
    private static int SomeNumber {get; set;}
    public static object SomeReference {get; set;}
    static ReflectStatic()
    {
        SomeReference = new object();
        Console.WriteLine(SomeReference.GetHashCode());
    }
}

public class Program
{
    public static void Main()
    {
        var rs = new ReflectStatic();
        var pi = rs.GetType().GetProperty("SomeReference",  BindingFlags.Static | BindingFlags.Public);
        if(pi == null) { Console.WriteLine("Null!"); Environment.Exit(0);}
        Console.WriteLine(pi.GetValue(rs, null).GetHashCode());


    }
}

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.