反映基类的私有字段

时间:2011-08-05 19:43:58

标签: c# .net reflection

这是结构:

MyClass:SuperClass2

SuperClass2:SuperClass1

superClass2位于Product.Web中,SuperClass1位于.NET System.Web程序集

我正在尝试将值强制为SuperClass1上的私有bool字段。但无论我尝试什么,我都无法让领域从反思中回归。

我正在使用以下代码与不同的BindingFlag组合,但到目前为止没有任何工作。 SuperClass1是一个抽象类。

((SuperClass1)this).GetType().GetFields(System.Reflection.BindingFlags.NonPublic);

备注: 当我使用GetProperties()时,我得到了一个很好的大清单,但是当我指定任何绑定标志时,即使有匹配的属性,我什么也得不到。什么交易?

此外,该字段未标记为内部

很明显我会使用GetField(字符串名称,BindingFlags),但我甚至无法使GetFlags()工作。

更新:我尝试按照建议添加BindingFlags.Instance,但它不起作用(无论如何都是预期的)。我找回了来自SuperClass1类继承自的2个字段。与GetField(字符串名称,标志)一起使用时返回null

以下是我试图获取

字段的基类的代码
public abstract class BaseValidator : Label, IValidator
  {
    private bool propertiesChecked;
...
}

5 个答案:

答案 0 :(得分:34)

您可以手动进入继承链以获取基本字段:

鉴于这些课程:

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答案中有一个更通用的解决方案:Not getting fields from GetType().GetFields with BindingFlag.Default

答案 1 :(得分:7)

与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);

答案 2 :(得分:3)

我认为您需要添加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)

答案 3 :(得分:3)

扩展方法:

authResponse

答案 4 :(得分:0)

如果层次结构是静态的,最简单的方法是执行此操作:

var field = typeof(SuperClass1).GetField("_privateBaseField",System.Reflection.BindingFlags.NonPublic);