Reflecting a private field from a base class
结构如下:
MyClass:超类2
超类2:超类1
superclass2在product.web中,superclass1在.net system.web程序集中
我试图将一个值强制到超类1上的私有布尔字段中。但无论我怎么尝试,我都无法让这些场从反射中回来。
我正在使用以下代码和不同的bindingflag组合,但到目前为止还没有任何效果。超类1是一个抽象类。
1 | ((SuperClass1)this).GetType().GetFields(System.Reflection.BindingFlags.NonPublic); |
笔记:当我使用get properties()时,我会得到一个很好的大列表,但是当我指定任何bindingFlags时,即使有匹配的属性,我也什么也得不到。这笔交易是什么?
此外,该字段未标记为"内部"
显然,我将使用getfield(字符串名称,bindingFlags),但我甚至无法让getFlags()工作。
更新:我已尝试按建议添加bindingFlags.Instance,但它不起作用(仍如预期的那样)。我得到了2个字段,它们来自类superclass1继承自。与GetField一起使用时返回空值(字符串名称、标志)
这是我要为其获取字段的基类的代码
1 2 3 4 5 | public abstract class BaseValidator : Label, IValidator { private bool propertiesChecked; ... } |
您可以在继承链中手动向上移动以获取基字段:
考虑到这些类别:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class SuperClass1 { private int myField; } class SuperClass2 : SuperClass1 { } class MyClass : SuperClass2 { } |
这应该有效:
1 2 3 4 |
这里面有一个更通用的解决方案,所以回答:不要从getType()中获取字段。getFields with bindingFlag.default
类似于经纪人的解决方案,你可以这样做,让它更通用一点:
1 2 3 | class Base { private int _baseField; } class Derived : Base { } class Mine : Derived { } |
然后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
作为一种实用方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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); } |
然后:
1 2 3 |
扩展方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /// <summary> /// 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. /// </summary> 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) is Type) ; return fi; } |
我认为您需要添加System.Reflection.BindingFlags.Instance标志。使用将其与非公共标志组合。
编辑:
好像是经纪人做的对。我写了下面的快速测试。
1 2 3 4 5 | var fields = test.GetType().BaseType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic); foreach (var field in fields) { System.Console.WriteLine(field.Name); } |
它正确地报告了您要查找的字段。(测试从basevalidator派生)
如果层次结构是静态的,那么最简单的方法是:
1 | var field = typeof(SuperClass1).GetField("_privateBaseField",System.Reflection.BindingFlags.NonPublic); |