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.

Corey Downie
fonte
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...
}
Ernest
fonte
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)

sem nome
fonte
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;
George
fonte
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)
Corey Downie
fonte
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.

Igor
fonte
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.

Andras Zoltan
fonte
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());


    }
}
Vyas Bharghava
fonte
-3

Experimente este link C # Reflection .

Observe que BindingFlags.Instance e BindingFlags.Static são exclusivos.

Ken Henderson
fonte
Sim espero que não seja o caso, pois o que desejo posso conseguir qualquer Instância Pública ou Estática.
Corey Downie
Eles não são exclusivos. Eu apenas testei.
LosManos