如何使用反射获取静态属性

134
所以这似乎非常基本,但我无法使其工作。我有一个对象,并且我正在使用反射来访问其公共属性。其中一个属性是静态的,我无法成功访问它。
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 反射器可以很好地查看静态属性,所以显然我在这里遗漏了什么。


这与以下链接非常相似: https://dev59.com/RHRC5IYBdhLWcg3wKtv2 - ctacke
嗯,它们都使用BindingFlags,这是相似的。我正在寻找一种特定的BindingFlags组合,它将允许我获取公共成员,无论它们是静态还是实例。 - Corey Downie
8个回答

172

或者只需查看此处...

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

3
这两个 null 值对应哪些变量?如果可能的话,你会如何使用命名参数来编写它?谢谢。 - Hamish Grubijan
对于内部静态类? - Kiquenet
这是最佳选择,我认为应该选择它作为答案。 - c0y0teX
17
p.GetValue(null); 也可以工作。第二个 null 不是必需的。 - Chrono
看起来很不错。目标是根据名称参数获取属性 - 我认为我不想遍历每个属性来实现这一点。 - Corey Downie
@Chrono,过去是这样,这也是为什么帖子包含它的原因。 - Bojidar Stanchev

52

这是 C# 的示例代码,但可以帮助你理解:

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

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

(您需要OR仅限于NonPublic和Static)


3
在我的情况下,仅使用这两个标志是不起作用的。我还必须使用.FlattenHierarchy标志。 - Corey Downie
3
@CoreyDownie同意了。对我而言,只有BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy有效。 - Jonathon Reinhart

51
一点澄清...
// 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

30

好的,对我来说关键是使用了.FlattenHierarchy BindingFlag。我不太清楚为什么,只是凭直觉加上它就开始工作了。所以最终允许我获取公共实例或静态属性的解决方案是:

obj.GetType.GetProperty(propName, Reflection.BindingFlags.Public _
  Or Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or _
  Reflection.BindingFlags.FlattenHierarchy)

9
myType.GetProperties(BindingFlags.Public | BindingFlags.Static |  BindingFlags.FlattenHierarchy);

这将返回静态基类或特定类型以及可能的子类中的所有静态属性。

4

我想澄清一下,使用基于 TypeInfo 的新反射API时 - 可靠地获取 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

是的,我希望不是这种情况,因为我想要能够获取任何公共实例或静态内容。 - Corey Downie
它们不是互斥的。我刚测试过了。 - LosManos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接