没有从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
有两个字段; PrivateString
和ProtectedString
。 B
有一个; ProtectedString
,它inheritance自A
如果您希望通过类型B
“到达” PrivateString
,则需要导航到其基本类型( b.GetType().BaseType
)。
但请注意,即使类型B
报告有一个名为ProtectedString
的字段,该字段仍未在B
声明; 它在A
声明。 这可以通过将BindingFlags.DeclaredOnly
添加到上面示例程序中的GetFields
调用来检查; GetFields
不会为B
返回任何字段,而为A
返回两个字段。
转换为您的代码示例,这意味着类型test3
不包含字段test2
和test3
,因为它们是类型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);