【问题标题】:Can I change a private readonly inherited field in C# using reflection?我可以使用反射更改 C# 中的私有只读继承字段吗?
【发布时间】:2010-11-26 22:50:44
【问题描述】:

就像在java中我有:

Class.getSuperClass().getDeclaredFields()

我如何知道和设置超类的私有字段?

我知道强烈不推荐这样做,但我正在测试我的应用程序,我需要模拟一个错误的情况,即 id 正确而名称不正确。但是这个 ID 是私有的。

【问题讨论】:

    标签: c# reflection inheritance superclass


    【解决方案1】:

    是的,可以在构造函数运行后使用反射来设置只读字段的值

    var fi = this.GetType()
                 .BaseType
                 .GetField("_someField", BindingFlags.Instance | BindingFlags.NonPublic);
    
    fi.SetValue(this, 1);
    

    编辑

    更新为查看直接父类型。如果类型是通用的,则此解决方案可能会出现问题。

    【讨论】:

    • 你现在为什么我只能使用“k__BackingField”来获取我的字段?
    【解决方案2】:

    是的,你可以。

    对于字段,使用FieldInfo 类。 BindingFlags.NonPublic 参数允许您查看私有字段。

    public class Base
    {
        private string _id = "hi";
    
        public string Id { get { return _id; } }
    }
    
    public class Derived : Base
    {
        public void changeParentVariable()
        {
            FieldInfo fld = typeof(Base).GetField("_id", BindingFlags.Instance | BindingFlags.NonPublic);
            fld.SetValue(this, "sup");
        }
    }
    

    还有一个小测试来证明它有效:

    public static void Run()
    {
        var derived = new Derived();
        Console.WriteLine(derived.Id); // prints "hi"
        derived.changeParentVariable();
        Console.WriteLine(derived.Id); // prints "sup"
    }
    

    【讨论】:

      【解决方案3】:

      这门课会让你做到:

      http://csharptest.net/browse/src/Library/Reflection/PropertyType.cs

      用法:

      new PropertyType(this.GetType(), "_myParentField").SetValue(this, newValue);
      

      顺便说一句,它将适用于公共/非公共领域或属性。为了便于使用,您可以像这样使用派生类PropertyValue

      new PropertyValue<int>(this,  "_myParentField").Value = newValue;
      

      【讨论】:

      • +1 用于 csharptest-net 库。它有一个有趣的记录器。
      【解决方案4】:

      就像 JaredPar 建议的那样,我执行了以下操作:

      //to discover the object type
      Type groupType = _group.GetType();
      //to discover the parent object type
      Type bType = groupType.BaseType;
      //now I get all field to make sure that I can retrieve the field.
      FieldInfo[] idFromBaseType = bType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
      
      //And finally I set the values. (for me, the ID is the first element)
      idFromBaseType[0].SetValue(_group, 1);
      

      谢谢大家。

      【讨论】:

      • 您确定 idFromBaseType[0] 是正确的字段吗?您可能应该按名称匹配...
      • 对我来说有效,因为我的第一个元素是 ID。但我试过用字符串获取字段,但没有成功。
      猜你喜欢
      • 2013-08-06
      • 2011-04-03
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-18
      • 2011-03-19
      相关资源
      最近更新 更多