没有从GetType()获取字段。使用BindingFlag.Default获取GetFields

我正在使用Reflection类来获取某个对象中的所有字段。 然而,我的问题是,当字段在普通类中时,它可以正常工作,例如:

class test { string test1 = string.Empty; string test2 = string.Empty; } 

在这里我得到test1和test2,我的问题是我使用抽象,因此结合了几个类。

我有类似的东西:

 class test3 : test2 { string test4 = string.Empty; string test5 = string.Empty; } class test2 : test1 { string test2 = string.Empty; string test3 = string.Empty; } class test1 { string test0 = string.Empty; string test1 = string.Empty; } 

但是当我运行它时,我没有从GetType().GetFields(BindingFlag.Default)获取字段GetType().GetFields(BindingFlag.Default)

这些领域的每个人都有财产, get; set; get; set; 附在它上面。 当我运行代码时,我将属性一直返回到test1但不是实际的字段。

这是我试图获取字段的代码:

 FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Default); foreach (FieldInfo field in fields) 

我也尝试过:

 FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); 

我对属性使用相同的代码:

 PropertyInfo[] properties = Obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); foreach (PropertyInfo property in properties) 

任何想法为什么我从抽象类而不是字段中获取属性?

编辑:要获取基本类型的私有成员,您必须:

 typeof(T).BaseType.GetFields(...) 

再次编辑:赢。

编辑3/22/13:使用Concat而不是Union 。 由于我们指定了BindingFlags.DeclaredOnly并且类型的BaseType不能等于自身,因此不需要Union ,而且更昂贵。

 public static IEnumerable GetAllFields(Type t) { if (t == null) return Enumerable.Empty(); BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; return t.GetFields(flags).Concat(GetAllFields(t.BaseType)); } 

inheritance另一种类型的类型无法看到该其他类型的私有部分,它可以看到受保护的内部和公共部分。 请考虑以下代码:

 class A { // note that this field is private string PrivateString = string.Empty; // protected field protected string ProtectedString = string.Empty; } class B : A { } class Program { static void Main(string[] args) { Console.WriteLine("B Fields:"); B b = new B(); b.GetType() .GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .ToList() .ForEach(f => Console.WriteLine(f.Name)); Console.WriteLine("A Fields:"); A a = new A(); a.GetType() .GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .ToList() .ForEach(f => Console.WriteLine(f.Name)); } } 

该程序的输出如下:

 B Fields: ProtectedString A Fields: PrivateString ProtectedString 

因此,类型A有两个字段; PrivateStringProtectedStringB有一个; ProtectedString ,它inheritance自A 如果您希望通过类型B “到达” PrivateString ,则需要导航到其基本类型( b.GetType().BaseType )。

但请注意,即使类型B报告有一个名为ProtectedString的字段,该字段仍未在B声明; 它在A声明。 这可以通过将BindingFlags.DeclaredOnly添加到上面示例程序中的GetFields调用来检查; GetFields不会为B返回任何字段,而为A返回两个字段。

转换为您的代码示例,这意味着类型test3不包含字段test2test3 ,因为它们是类型test2私有(字段名称和类型名称的相似性使得该句子有点混乱,我担心)。一个

您可以使用此扩展方法以递归方式遍历类型的inheritance层次结构一直到对象,从而有效地返回该类型及其所有祖先的所有字段:

 public static class ReflectionExtensions { public static IList GetAllFields(this Type type, BindingFlags flags) { if(type == typeof(Object)) return new List(); var list = type.BaseType.GetAllFields(flags); // in order to avoid duplicates, force BindingFlags.DeclaredOnly list.AddRange(type.GetFields(flags | BindingFlags.DeclaredOnly)); return list; } } 

(未经测试,YMMV)

属性是inheritance的,字段不是。 受保护的字段对后代类是可见的,但不会被它们inheritance。 换句话说,后代类实际上具有其基类的属性,但它只能看到字段。

如果您只想要属性和字段的名称,请使用

 private static IEnumerable GetAllFieldsAndProperties(Type t) { if (t == null) return Enumerable.Empty(); BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; return t.GetFields(flags).Select(x=>x.Name) .Union(GetAllFieldsAndProperties(t.BaseType)) .Union(t.GetProperties(flags).Select(x=>x.Name)); } 

枚举所有类型字段,包括基类中的私有成员。

 public static IEnumerable EnumerateFields(this Type type, BindingFlags flags) => type.BaseType?.EnumerateFields(flags) .Concat(type.GetFields(flags | BindingFlags.DeclaredOnly)) ?? type.EnumerateFields(flags); 
Interesting Posts