So erhalten Sie eine statische Eigenschaft mit Reflection

109

Das scheint also ziemlich einfach zu sein, aber ich kann es nicht zum Laufen bringen. Ich habe ein Objekt und verwende Reflexion, um zu seinen öffentlichen Eigenschaften zu gelangen. Eine dieser Eigenschaften ist statisch und ich habe kein Glück, sie zu erreichen.

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

End Function

Der obige Code funktioniert gut für Eigenschaften öffentlicher Instanzen, was bis jetzt alles ist, was ich benötigt habe. Angeblich kann ich BindingFlags verwenden, um andere Arten von Eigenschaften (privat, statisch) anzufordern, aber ich kann anscheinend nicht die richtige Kombination finden.

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

Wenn Sie jedoch statische Mitglieder anfordern, wird nichts zurückgegeben. Der .NET-Reflektor kann die statischen Eigenschaften gut erkennen, daher fehlt mir hier eindeutig etwas.

Corey Downie
quelle
Dies ist wirklich sehr, sehr ähnlich zu diesem: stackoverflow.com/questions/392122/…
ctacke
Nun, es ist insofern ähnlich, als beide BindingFlags verwenden. Ich suche nach einer bestimmten Kombination von BindingFlags, mit der ich öffentliche Mitglieder gewinnen kann, sei es statisch oder instanziell.
Corey Downie

Antworten:

129

Oder schau dir das an ...

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
quelle
2
Welchen Variablen entsprechen diese beiden Nullen? Wie würden Sie dies mit benannten Argumenten schreiben, wenn es möglich ist? Vielen Dank.
Hamish Grubijan
Für interne statische Klasse?
Kiquenet
Dies ist die beste Option, meiner Meinung nach sollte sie als Antwort ausgewählt werden.
c0y0teX
8
p.GetValue(null);funktioniert auch. Der zweite nullist nicht erforderlich.
Chrono
Sieht großartig aus. Das Ziel war es, die Eigenschaft basierend auf einem Namensargument zu erhalten - ich glaube nicht, dass ich jemals eine Eigenschaft durchlaufen möchte, um dies zu erreichen.
Corey Downie
42

Dies ist C #, sollte Ihnen aber die Idee geben:

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

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

(Sie müssen nur nicht öffentlich und statisch ODER)

EarlNameless
quelle
3
In meinem Fall hat es nicht funktioniert, nur diese beiden Flags zu verwenden. Ich musste auch das Flag .FlattenHierarchy verwenden.
Corey Downie
3
@CoreyDownie stimmte zu. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchywar das einzige, was für mich funktioniert hat.
Jonathon Reinhart
39

Ein bisschen Klarheit ...

// 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
quelle
1
BindingFlags.Instance | BindingFlags.Staticlöste es für mich.
LosManos
28

Ok, der Schlüssel für mich war die Verwendung des .FlattenHierarchy BindingFlag. Ich weiß nicht wirklich, warum ich es gerade hinzugefügt habe und es begann zu funktionieren. Die endgültige Lösung, mit der ich öffentliche Instanzen oder statische Eigenschaften erhalten kann, lautet:

obj.GetType.GetProperty(propName, Reflection.BindingFlags.Public _
  Or Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or _
  Reflection.BindingFlags.FlattenHierarchy)
Corey Downie
quelle
7
myType.GetProperties(BindingFlags.Public | BindingFlags.Static |  BindingFlags.FlattenHierarchy);

Dadurch werden alle statischen Eigenschaften in der statischen Basisklasse oder einem bestimmten Typ und wahrscheinlich auch das untergeordnete Element zurückgegeben.

Igor
quelle
2

Ich wollte dies nur für mich selbst klären, während ich die neue Reflection-API verwendete, die auf TypeInfo- wo BindingFlagsnicht zuverlässig verfügbar ist (abhängig vom Ziel-Framework).

Um die statischen Eigenschaften für einen Typ (ohne Basisklasse (n)) zu erhalten, müssen Sie in der 'neuen' Reflexion Folgendes tun:

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

Bietet sowohl schreibgeschützte als auch schreibgeschützte Eigenschaften (obwohl das Nur-Schreiben eine schreckliche Idee ist).

Auch das DeclaredPropertiesMitglied unterscheidet nicht zwischen Eigenschaften mit öffentlichen / privaten Accessoren. Um die Sichtbarkeit zu filtern, müssen Sie dies dann basierend auf dem Accessor tun, den Sie verwenden müssen. Beispiel: Wenn der obige Anruf zurückgekehrt ist, können Sie Folgendes tun:

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

Es gibt einige Verknüpfungsmethoden - aber letztendlich werden wir alle in Zukunft viel mehr Erweiterungsmethoden um die TypeInfoAbfragemethoden / -eigenschaften schreiben . Außerdem zwingt uns die neue API, von nun an genau darüber nachzudenken, was wir als "privates" oder "öffentliches" Eigentum betrachten - weil wir uns nach einzelnen Zugriffsmethoden filtern müssen.

Andras Zoltan
quelle
1

Das Folgende scheint für mich zu funktionieren.

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
quelle
-3

Versuchen Sie diesen C # Reflection Link.

Hinweis Ich denke, dass BindingFlags.Instance und BindingFlags.Static exklusiv sind.

Ken Henderson
quelle
Ja, ich hoffe, dass dies nicht der Fall ist, denn was ich möchte, ist, dass ich in der Lage bin, eine öffentliche Instanz oder Statik zu erhalten.
Corey Downie
Sie sind nicht exklusiv. Ich habe es gerade getestet.
LosManos