Cómo obtener una propiedad estática con Reflection


109

Así que esto parece bastante básico, pero no puedo hacerlo funcionar. Tengo un objeto y estoy usando la reflexión para llegar a sus propiedades públicas. Una de estas propiedades es estática y no tengo suerte para acceder a ella.

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

End Function

El código anterior funciona bien para las propiedades de instancia pública, que hasta ahora es todo lo que necesitaba. Supuestamente puedo usar BindingFlags para solicitar otros tipos de propiedades (privadas, estáticas), pero parece que no puedo encontrar la combinación correcta.

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

Pero aún así, solicitar que cualquier miembro de Static no devuelva nada. El reflector .NET puede ver las propiedades estáticas muy bien, así que claramente me falta algo aquí.


Esto es muy, muy similar a esto: stackoverflow.com/questions/392122/…
ctacke

Bueno, es similar en que ambos usan BindingFlags. Estoy buscando una combinación específica de BindingFlags que me permita obtener miembros públicos, ya sean estáticos o de instancia.
Corey Downie

Respuestas:


129

O simplemente mira esto ...

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 qué variables corresponden estos dos nulos? ¿Cómo escribirías esto usando argumentos con nombre, si es posible? Gracias.
Hamish Grubijan

¿Para clase estática interna?
Kiquenet

Esta es la mejor opción, en mi opinión debería seleccionarse como respuesta.
c0y0teX

8
p.GetValue(null);también funciona. El segundo nullno es obligatorio.
Chrono

Se ve muy bien. El objetivo era obtener la propiedad en función de un argumento de nombre; no creo que quisiera recorrer todas las propiedades para lograrlo.
Corey Downie

42

Esto es C #, pero debería darte la idea:

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

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

(necesita OR NonPublic y Static solamente)


3
En mi caso, usar solo estas dos banderas no funcionó. También tuve que usar la bandera .FlattenHierarchy.
Corey Downie

3
@CoreyDownie estuvo de acuerdo. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchyfue lo único que funcionó para mí.
Jonathon Reinhart

40

Un poco de claridad ...

// 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.Staticme lo resolvió.
LosManos

28

Ok, entonces la clave para mí fue usar .FlattenHierarchy BindingFlag. Realmente no sé por qué lo agregué por una corazonada y comenzó a funcionar. Entonces, la solución final que me permite obtener Instancia pública o Propiedades estáticas es:

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);

Esto devolverá todas las propiedades estáticas en la clase base estática o un tipo en particular y probablemente también el hijo.


2

Solo quería aclarar esto por mí mismo, mientras utilizo la nueva API de reflexión basada en TypeInfo- donde BindingFlagsno está disponible de manera confiable (según el marco de trabajo de destino).

En la reflexión 'nueva', para obtener las propiedades estáticas de un tipo (sin incluir las clases base), debe hacer algo como:

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

Se adapta tanto a propiedades de solo lectura como de solo escritura (a pesar de que solo escritura es una idea terrible).

El DeclaredPropertiesmiembro tampoco distingue entre propiedades con descriptores de acceso públicos / privados; por lo tanto, para filtrar la visibilidad, debe hacerlo en función del descriptor de acceso que necesite utilizar. Por ejemplo, suponiendo que la llamada anterior haya regresado, podría hacer:

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

Hay algunos métodos de acceso directo disponibles, pero en última instancia, todos escribiremos muchos más métodos de extensión en torno a los TypeInfométodos / propiedades de consulta en el futuro. Además, la nueva API nos obliga a pensar exactamente en lo que consideramos una propiedad 'privada' o 'pública' a partir de ahora, porque debemos filtrarnos en función de los accesos individuales.


1

Lo siguiente parece funcionar para mí.

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());


    }
}

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.