Это кажется довольно простым, но я не могу заставить его работать. У меня есть объект, и я использую отражение, чтобы добраться до его общедоступных свойств. Одно из этих свойств является статическим, и мне не удалось до него добраться.
Public Function GetProp(ByRef obj As Object, ByVal propName as String) as PropertyInfo
Return obj.GetType.GetProperty(propName)
End Function
Приведенный выше код отлично работает для свойств Public Instance, что до сих пор было всем, что мне было нужно. Предположительно я могу использовать 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 прекрасно видит статические свойства, так что мне явно чего-то не хватает.
Это похоже на то, что они оба используют BindingFlags. Я ищу конкретную комбинацию BindingFlags, которая позволит мне получить публичные члены, будь то статические или экземпляры.





Это C#, но он должен дать вам представление:
public static void Main() {
typeof(Program).GetProperty("GetMe", BindingFlags.NonPublic | BindingFlags.Static);
}
private static int GetMe {
get { return 0; }
}
(вам нужно ИЛИ только NonPublic и Static)
В моем случае использование только этих двух флагов не сработало. Мне также пришлось использовать флаг .FlattenHierarchy.
@CoreyDownie согласился. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy был единственным, что у меня сработало.
Попробуйте эту ссылку C# Отражение.
Обратите внимание, я думаю, что BindingFlags.Instance и BindingFlags.Static являются исключительными.
Да, я надеюсь, что это не так, потому что я хочу, чтобы я мог получить любой общедоступный или статический экземпляр.
Они не исключительны. Я только что это проверил.
Кажется, что ниже работает для меня.
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());
}
}
Итак, ключевым моментом для меня было использование BindingFlag .FlattenHierarchy. Я действительно не знаю, почему я просто добавил это на догадке, и он начал работать. Итак, окончательное решение, которое позволяет мне получить общедоступный экземпляр или статические свойства:
obj.GetType.GetProperty(propName, Reflection.BindingFlags.Public _
Or Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or _
Reflection.BindingFlags.FlattenHierarchy)
Или просто посмотрите на это ...
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...
}
Каким переменным соответствуют эти два нуля? Как бы вы написали это, используя именованные аргументы, если это возможно? Спасибо.
Для внутреннего статического класса?
Это лучший вариант, на мой взгляд, его следует выбрать в качестве ответа.
p.GetValue(null); тоже работает. Второй null не требуется.
Выглядит отлично. Цель заключалась в том, чтобы получить свойство на основе аргумента имени - я не думаю, что мне нужно было бы перебирать любое свойство для достижения этого.
@Chrono, раньше было, поэтому в посте это было.
myType.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
Это вернет все статические свойства в статическом базовом классе или конкретном типе, а также, возможно, в дочернем.
Немного ясности ...
// 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;
BindingFlags.Instance | BindingFlags.Static решил это за меня.
Просто хотел прояснить это для себя при использовании нового 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 заставляет нас думать о том, что с этого момента мы считаем «частным» или «общедоступным» свойством, потому что мы должны фильтровать себя на основе индивидуальных средств доступа.
Это действительно очень похоже на это: stackoverflow.com/questions/392122/…