如何获取类/基类私有属性?为何单独可获取的属性未被枚举?
问题解答:反射获取单个属性成功但遍历成员找不到的原因
这个问题我之前也碰到过,其实核心在于反射方法对继承成员的处理逻辑差异,咱们一步步理清楚:
首先,你用以下代码能成功拿到Age属性:
BindingFlags flags= BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; PropertyInfo prop = myObj.GetProperty("Age", flags);
但调用GetMembers(flags)遍历所有成员时却看不到它,大概率是因为这个Age属性是从父类继承来的非公共属性(比如protected或者internal,并非当前类自身定义的)。
核心差异点
GetProperty方法在指定BindingFlags.Instance | Public | NonPublic时,会自动向上遍历继承链查找属性,不管它是当前类还是父类定义的;- 但
GetMembers(或GetProperties)默认只搜索当前类型的成员,不会去父类中查找,除非你额外添加BindingFlags.FlattenHierarchy标记——它会让反射包含所有继承自父类的公共和受保护成员(注意:父类的私有成员仍无法获取,因为私有成员本身不支持继承访问)。
解决方法
修改flags添加BindingFlags.FlattenHierarchy,就能在遍历中看到Age属性了:
BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy; // 用GetProperties会更精准,因为GetMembers会返回所有类型的成员(方法、字段、属性等) foreach(PropertyInfo prop in myObj.GetType().GetProperties(flags)) { Console.WriteLine(prop.Name); }
验证方式
你可以打印属性的定义类型和当前对象的类型,确认属性是否来自父类:
Console.WriteLine($"属性定义类型:{prop.DeclaringType.FullName}"); Console.WriteLine($"当前对象类型:{myObj.GetType().FullName}");
如果两者不一致,就说明Age确实是父类定义的属性,这也解释了为什么之前遍历看不到它。
内容的提问来源于stack exchange,提问作者T.Todua
相关产品推荐
相关产品推荐

