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


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的特定组合,使我能够获取Public成员,无论是Static还是Instance。
Corey Downie

Answers:


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 2012年

对于内部静态类?
Kiquenet '16

这是最好的选择,我认为应该选择它作为答案。
c0y0teX

8
p.GetValue(null);也可以。null不需要第二个。
计时

看起来很棒。目标是根据名称参数获取属性-我认为我不希望遍历任何属性来实现这一点。
科里·唐尼

42

这是C#,但是应该给你一个主意:

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

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

(您只需要OR非公开和静态)


3
就我而言,仅使用这两个标志是行不通的。我还必须使用.FlattenHierarchy标志。
Corey Downie

3
@CoreyDownie同意。BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy是唯一对我有用的东西。
乔纳森·莱因哈特

39

有点清晰...

// 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

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

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

只是想为我自己澄清这一点,同时使用基于TypeInfo-的BindingFlags可靠的新API,其中where 可靠使用(取决于目标框架)。

在“新”反映中,要获取类型(不包括基类)的静态属性,您必须执行以下操作:

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


    }
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.