Jak uzyskać właściwość statyczną za pomocą odbicia

109

Wydaje się to dość proste, ale nie mogę go uruchomić. Mam obiekt i używam odbicia, aby dostać się do jego właściwości publicznych. Jedna z tych właściwości jest statyczna i nie udało mi się do niej dotrzeć.

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

End Function

Powyższy kod działa dobrze dla właściwości Instancji Publicznej, które do tej pory są wszystkim, czego potrzebowałem. Podobno mogę użyć BindingFlags do zażądania innych typów właściwości (prywatnych, statycznych), ale nie mogę znaleźć odpowiedniej kombinacji.

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

Mimo to żądanie jakichkolwiek członków statycznych nic nie zwraca. Odbłyśnik .NET dobrze widzi właściwości statyczne, więc wyraźnie czegoś mi brakuje.

Corey Downie
źródło
To jest naprawdę bardzo podobne do tego: stackoverflow.com/questions/392122/…
ctacke
Cóż, jest podobnie, ponieważ obaj używają BindingFlags. Szukam konkretnej kombinacji BindingFlags, która pozwoli mi uzyskać członków publicznych, zarówno statycznych, jak i instancji.
Corey Downie

Odpowiedzi:

129

Albo po prostu spójrz na to ...

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
źródło
2
Którym zmiennym odpowiadają te dwie wartości null? Jak byś to napisał, używając nazwanych argumentów, jeśli jest to możliwe? Dzięki.
Hamish Grubijan
Do wewnętrznej klasy statycznej?
Kiquenet,
To najlepsza opcja, moim zdaniem powinna zostać wybrana jako odpowiedź.
c0y0teX
8
p.GetValue(null);działa też. Drugi nullnie jest wymagany.
Chrono
Wygląda świetnie. Celem było uzyskanie właściwości na podstawie argumentu nazwy - nie sądzę, żebym chciałby zapętlić kiedykolwiek właściwość, aby to osiągnąć.
Corey Downie
42

To jest C #, ale powinno dać ci pomysł:

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

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

(musisz LUB tylko niepubliczne i statyczne)

EarlNameless
źródło
3
W moim przypadku użycie tylko tych dwóch flag nie zadziałało. Musiałem również użyć flagi .FlattenHierarchy.
Corey Downie,
3
@CoreyDownie zgodził się. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchybyła jedyną rzeczą, która działała dla mnie.
Jonathon Reinhart
40

Trochę jasności ...

// 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;
Jerzy
źródło
1
BindingFlags.Instance | BindingFlags.Staticrozwiązał to dla mnie.
LosManos,
28

Ok, więc kluczem dla mnie było użycie FlattenHierarchy BindingFlag. Naprawdę nie wiem, dlaczego po prostu dodałem go z przeczucia i zaczęło działać. Ostatnim rozwiązaniem, które pozwala mi uzyskać instancję publiczną lub właściwości statyczne, jest:

obj.GetType.GetProperty(propName, Reflection.BindingFlags.Public _
  Or Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or _
  Reflection.BindingFlags.FlattenHierarchy)
Corey Downie
źródło
7
myType.GetProperties(BindingFlags.Public | BindingFlags.Static |  BindingFlags.FlattenHierarchy);

Spowoduje to zwrócenie wszystkich statycznych właściwości w statycznej klasie bazowej lub określonego typu i prawdopodobnie również elementu podrzędnego.

Igor
źródło
2

Chciałem tylko to sobie wyjaśnić, korzystając z nowego interfejsu API refleksji opartego na TypeInfo- gdzie BindingFlagsnie jest dostępne niezawodnie (w zależności od docelowego frameworka).

W `` nowym '' odbiciu, aby uzyskać właściwości statyczne dla typu (bez klas bazowych), musisz zrobić coś takiego:

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

Obsługuje zarówno właściwości tylko do odczytu, jak i tylko do zapisu (mimo że tylko zapis jest okropnym pomysłem).

DeclaredPropertiesCzłonek też nie rozróżnia właściwości z publicznych / prywatnych dostępowych - tak aby filtrować widoczność dookoła, następnie trzeba to zrobić w oparciu o akcesor trzeba użyć. Np. - zakładając, że powyższe wezwanie powróciło, możesz:

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

Dostępnych jest kilka metod skrótów - ale ostatecznie wszyscy będziemy pisać o wiele więcej metod rozszerzających dotyczących TypeInfometod / właściwości zapytań w przyszłości. Ponadto nowy interfejs API zmusza nas do zastanowienia się nad tym, co od teraz uważamy za własność „prywatną” lub „publiczną” - ponieważ musimy filtrować się w oparciu o indywidualne metody dostępu.

Andras Zoltan
źródło
1

Poniższe wydaje się działać dla mnie.

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
źródło
-3

Wypróbuj ten link odbicia C # .

Uwaga: Myślę, że BindingFlags.Instance i BindingFlags.Static są wyłączne.

Ken Henderson
źródło
Tak, mam nadzieję, że tak nie jest, ponieważ chcę mieć możliwość uzyskania dowolnej instancji publicznej lub statycznej.
Corey Downie
Nie są wyłączne. Właśnie to przetestowałem.
LosManos,