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.


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...
}

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)


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;

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)

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.


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.


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


    }
}

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.