繁体   English   中英

通过反射设置只读属性值

[英]Set readonly property value through reflection

我需要修改仅具有“ get”选项的属性值。 我发现使用GetField有一些技巧,但是没有成功。

参见下面的代码:

namespace ConsoleApplication1
{
  abstract class Test
  {
    private int testValue;
    protected int TestValue {
        get { return testValue; }
    }
  }
  class Myclass : Test
  {
    public Myclass(): base(){}
  }  

  class Program
  {
    static void Main(string[] args)
    {
      Myclass test = new Myclass();

      var field = typeof(Myclass).GetField("<TestValue>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance);
      field.SetValue(test, 3);

    }
  }
}

实际上,我想将“ TestValue”设置为值3,但它不起作用。 我可能做错了。

您找到的“技巧”依赖于自动实现的属性( string Foo { get; } ),这些属性会编译为带有后备字段的属性(因此,您要查找的成员的名称)。 请注意,这非常脆弱,因为未记录生成的成员名称。 但是,从一开始就依靠反射来访问类型的成员是脆弱的。

但是,您没有自动实现的属性,您只需要访问该属性公开的名为testValue的私有字段testValue

但是GetField()不处理非公共成员的继承,因此请参见派生类型的GetFields 此方法将帮助您:

public static void Main()
{
    Myclass test = new Myclass();

    var field = GetInheritedPrivateField(test.GetType(), "testValue");

    field.SetValue(test, 3);
}

private static FieldInfo GetInheritedPrivateField(Type type, string fieldName)
{
    do
    {
        var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

        if (field != null)
        {
            return field;
        }

        type = type.BaseType;
    } 
    while (type != null);

    return null;
}

您可以检索Test类的字段信息,并使用它来设置派生类实例上的值,如下所示:

var field = typeof(Test).GetField("testValue", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(test, 3);

没有“设置者”,就无法为属性设置值。

如果您不希望该属性被范围外的其他对象覆盖,则可以使用“ private set”作为设置器,然后可以在范围内设置值。

另一种方法是编写一种方法来设置属性的getter值。

 class Myclass : Test
  {
    public Myclass(): base(){}

    public void SetValue(int value) { this.testValue=value; }
  }  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM