Come ottenere una proprietà statica con Reflection


109

Quindi questo sembra piuttosto semplice ma non riesco a farlo funzionare. Ho un oggetto e utilizzo la riflessione per accedere alle sue proprietà pubbliche. Una di queste proprietà è statica e non ho fortuna ad arrivarci.

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

End Function

Il codice sopra funziona bene per le proprietà dell'istanza pubblica, che fino ad ora è tutto ciò di cui avevo bisogno. Presumibilmente posso usare BindingFlags per richiedere altri tipi di proprietà (private, statiche), ma non riesco a trovare la giusta combinazione.

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

Tuttavia, la richiesta di qualsiasi membro statico non restituisce nulla. Il riflettore .NET può vedere le proprietà statiche bene, quindi chiaramente mi manca qualcosa qui.


Questo è molto, molto simile a questo: stackoverflow.com/questions/392122/...
ctacke

Bene, è simile in quanto entrambi usano BindingFlags. Sto cercando una combinazione specifica di BindingFlags che mi permetta di ottenere membri pubblici, siano essi statici o istanze.
Corey Downie

Risposte:


129

O guarda questo ...

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 quali variabili corrispondono questi due valori nulli? Come scriveresti questo usando argomenti con nome, se possibile? Grazie.
Hamish Grubijan

Per classe statica interna?
Kiquenet

Questa è l'opzione migliore, secondo me dovrebbe essere selezionata come risposta.
c0y0teX

8
p.GetValue(null);funziona anche. Il secondo nullnon è richiesto.
Chrono

Sembra fantastico. L'obiettivo era quello di ottenere la proprietà in base a un argomento di nome: non penso che vorrei eseguire il ciclo su una qualsiasi proprietà per ottenerlo.
Corey Downie

42

Questo è C #, ma dovrebbe darti l'idea:

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

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

(è necessario OR Non pubblico e solo statico)


3
Nel mio caso, usare solo questi due flag non ha funzionato. Ho dovuto usare anche il flag .FlattenHierarchy.
Corey Downie

3
@CoreyDownie ha accettato. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchyera l'unica cosa che ha funzionato per me.
Jonathon Reinhart

40

Un po 'di chiarezza ...

// 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.Staticrisolto per me.
LosManos

28

Ok, quindi la chiave per me era usare .FlattenHierarchy BindingFlag. Non so davvero perché l'ho aggiunto per intuizione e ha iniziato a funzionare. Quindi la soluzione finale che mi permette di ottenere istanze pubbliche o proprietà statiche è:

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

Ciò restituirà tutte le proprietà statiche nella classe base statica o in un tipo particolare e probabilmente anche nel figlio.


2

Volevo solo chiarire questo per me stesso, mentre utilizzavo la nuova API di riflessione basata su TypeInfo- doveBindingFlags non è disponibile in modo affidabile (a seconda del framework di destinazione).

Nella riflessione 'nuova', per ottenere le proprietà statiche per un tipo (escluse le classi base) devi fare qualcosa come:

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

Fornisce proprietà di sola lettura o di sola scrittura (nonostante la sola scrittura sia un'idea terribile).

Anche il DeclaredPropertiesmembro non distingue tra proprietà con funzioni di accesso pubbliche / private, quindi per filtrare la visibilità, devi farlo in base alla funzione di accesso che devi utilizzare. Ad esempio, supponendo che la chiamata di cui sopra sia tornata, potresti fare:

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

Sono disponibili alcuni metodi di scelta rapida, ma alla fine scriveremo tutti molti più metodi di estensione sui TypeInfometodi / proprietà di query in futuro. Inoltre, la nuova API ci costringe a pensare esattamente a ciò che pensiamo come una proprietà "privata" o "pubblica" da ora in poi, perché dobbiamo filtrare noi stessi in base ai singoli accessor.


1

Quanto segue sembra funzionare per me.

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


    }
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.