反映基类的私有字段
这是结构:
MyClass:SuperClass2
SuperClass2:SuperClass1
superClass2位于Product.Web中,SuperClass1位于.NET System.Web程序集中
我试图强制一个值进入SuperClass1上的私有bool字段。 但无论我尝试什么,我都无法让领域从反思中回归。
我使用以下代码与不同的BindingFlag组合,但到目前为止没有任何工作。 SuperClass1是一个抽象类。
((SuperClass1)this).GetType().GetFields(System.Reflection.BindingFlags.NonPublic);
注意:当我使用GetProperties()时,我得到了一个很好的大列表,但是当我指定任何bindingflags时,即使有匹配的属性,我也什么也得不到。 这是怎么回事?
此外,该字段未标记为内部
显然我会使用GetField(字符串名称,BindingFlags),但我甚至无法使GetFlags()工作。
更新 :我已经尝试按照建议添加BindingFlags.Instance,但它不起作用(无论如何都是预期的)。 我找回了来自SuperClass1类inheritance自的2个字段。 与GetField一起使用时返回null(字符串名称,标志)
这是我试图获取该字段的基类的代码
public abstract class BaseValidator : Label, IValidator { private bool propertiesChecked; ... }
您可以手动进入inheritance链以获取基本字段:
鉴于这些类:
class SuperClass1 { private int myField; } class SuperClass2 : SuperClass1 { } class MyClass : SuperClass2 { }
这应该工作:
var myObj = new MyClass(); var myField = typeof(MyClass).BaseType .BaseType .GetField("myField", BindingFlags.Instance | BindingFlags.NonPublic);
在这个SO答案中有一个更通用的解决方案: 没有从GetType()获取字段。具有BindingFlag.Default的GetFields
与BrokenGlass的解决方案类似,你可以这样做,使它更通用:
class Base { private int _baseField; } class Derived : Base { } class Mine : Derived { }
然后:
Type t = typeof(Mine); FieldInfo fi = null; while (t != null) { fi = t.GetField("_baseField", BindingFlags.Instance | BindingFlags.NonPublic); if (fi != null) break; t = t.BaseType; } if (fi == null) { throw new Exception("Field '_baseField' not found in type hierarchy."); }
作为一种实用方法:
public static void SetField(object target, string fieldName, object value) { if (target == null) { throw new ArgumentNullException("target", "The assignment target cannot be null."); } if (string.IsNullOrEmpty(fieldName)) { throw new ArgumentException("fieldName", "The field name cannot be null or empty."); } Type t = target.GetType(); FieldInfo fi = null; while (t != null) { fi = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); if (fi != null) break; t = t.BaseType; } if (fi == null) { throw new Exception(string.Format("Field '{0}' not found in type hierarchy.", fieldName)); } fi.SetValue(target, value); }
然后:
Mine m = new Mine(); SetField(m, "_baseField", 10);
我认为你需要添加System.Reflection.BindingFlags.Instance标志。 使用| 将它与NonPublic标志结合起来。
编辑:
看起来像BrokenGlass是对的。 我写了以下快速测试。
var fields = test.GetType().BaseType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic); foreach (var field in fields) { System.Console.WriteLine(field.Name); }
它会正确报告您要查找的字段。 (测试来自BaseValidator)
扩展方法:
/// /// Returns the FieldInfo matching 'name' from either type 't' itself or its most-derived /// base type (unlike 'System.Type.GetField'). Returns null if no match is found. /// public static FieldInfo GetPrivateField(this Type t, String name) { const BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly; FieldInfo fi; while ((fi = t.GetField(name, bf)) == null && (t = t.BaseType) != null) ; return fi; }
如果层次结构是静态的,最简单的方法是:
var field = typeof(SuperClass1).GetField("_privateBaseField",System.Reflection.BindingFlags.NonPublic);