Как получить статическое свойство с помощью Reflection

109

Это кажется довольно простым, но я не могу заставить его работать. У меня есть объект, и я использую отражение, чтобы добраться до его общедоступных свойств. Одно из этих свойств статично, и мне не удалось до него добраться.

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

End Function

Приведенный выше код отлично работает для свойств общедоступного экземпляра, что до сих пор было всем, что мне было нужно. Предположительно я могу использовать BindingFlags для запроса других типов свойств (частных, статических), но я не могу найти правильную комбинацию.

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

Но все же запрос любых статических членов ничего не возвращает. Рефлектор .NET прекрасно видит статические свойства, так что я явно чего-то упускаю.

Кори Дауни
источник
Это действительно очень похоже на это: stackoverflow.com/questions/392122/…
ctacke
Это похоже на то, что они оба используют BindingFlags. Я ищу конкретную комбинацию BindingFlags, которая позволит мне получить публичные члены, будь то статические или экземпляры.
Кори Дауни

Ответы:

129

Или просто посмотрите на это ...

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
Каким переменным соответствуют эти два нуля? Как бы вы написали это, используя именованные аргументы, если это возможно? Спасибо.
Hamish Grubijan,
Для внутреннего статического класса?
Kiquenet
Это лучший вариант, на мой взгляд, его следует выбрать как ответ.
c0y0teX
8
p.GetValue(null);тоже работает. Второго nullне требуется.
Chrono
Выглядит отлично. Цель состояла в том, чтобы получить свойство на основе аргумента имени - я не думаю, что мне нужно было бы перебирать любое свойство для достижения этого.
Кори Дауни,
42

Это C #, но он должен дать вам представление:

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

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

(вам нужно ИЛИ только NonPublic и Static)

EarlNameless
источник
3
В моем случае использование только этих двух флагов не сработало. Мне также пришлось использовать флаг .FlattenHierarchy.
Кори Дауни
3
@CoreyDownie согласился. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchyбыло единственное, что сработало для меня.
Джонатон Рейнхарт
40

Немного ясности ...

// 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.Staticрешил это за меня.
LosManos
28

Итак, ключевым моментом для меня было использование BindingFlag .FlattenHierarchy. Я действительно не знаю, почему я просто добавил это на догадке, и он начал работать. Итак, окончательное решение, которое позволяет мне получить общедоступный экземпляр или статические свойства:

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

Это вернет все статические свойства в статическом базовом классе или определенном типе, а также, возможно, в дочернем.

Игорь
источник
2

Просто хотел прояснить это для себя, используя новый API отражения, основанный на TypeInfo- где BindingFlagsнедоступен надежно (в зависимости от целевой платформы).

В «новом» отражении, чтобы получить статические свойства для типа (не включая базовый класс (а)), вам нужно сделать что-то вроде:

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

Подходит как для свойств только для чтения, так и для свойств только для записи (несмотря на то, что только запись - ужасная идея).

DeclaredPropertiesЧлен тоже не различает свойства с государственными / частным аксессорами - так фильтр вокруг видимости, то вы должны сделать это на основе аксессора вам нужно использовать. Например, если вышеупомянутый вызов вернулся, вы можете:

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

Есть несколько доступных методов быстрого доступа, но в конечном итоге мы все собираемся писать намного больше методов расширения для TypeInfoметодов / свойств запросов в будущем. Кроме того, новый API заставляет нас думать о том, что с этого момента мы считаем «частным» или «общедоступным» свойством, потому что мы должны фильтровать себя на основе отдельных средств доступа.

Андраш Золтан
источник
1

Кажется, что ниже работает для меня.

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


    }
}
Вьяс Бхаргхава
источник
-3

Попробуйте эту ссылку C # Reflection .

Примечание. Я считаю, что BindingFlags.Instance и BindingFlags.Static являются исключительными.

Кен Хендерсон
источник
Да, я надеюсь, что это не так, потому что я хочу, чтобы я мог получить любой общедоступный или статический экземпляр.
Кори Дауни
Они не исключительны. Я только что это протестировал.
LosManos