简体   繁体   English

通过反射设置只读属性值

[英]Set readonly property value through reflection

I need to modify a property value which has only "get" option. 我需要修改仅具有“ get”选项的属性值。 I have found some trick with using GetField but I did not succeed. 我发现使用GetField有一些技巧,但是没有成功。

See below the code: 参见下面的代码:

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

    }
  }
}

Actually, I would like to set "TestValue" with a the value 3 but it is not working. 实际上,我想将“ TestValue”设置为值3,但它不起作用。 I do probably something wrong. 我可能做错了。

The "trick" you found relies on auto-implemented properties ( string Foo { get; } ) that compile into a property with a backing field (hence the name of the member you're looking up). 您找到的“技巧”依赖于自动实现的属性( string Foo { get; } ),这些属性会编译为带有后备字段的属性(因此,您要查找的成员的名称)。 Do note that this is extremely fragile, as the generated member name isn't documented. 请注意,这非常脆弱,因为未记录生成的成员名称。 But hey, relying on reflection to access a type's members is fragile to begin with. 但是,从一开始就依靠反射来访问类型的成员是脆弱的。

You don't have an auto-implemented property though, you just need to access the private field named testValue which the property exposes. 但是,您没有自动实现的属性,您只需要访问该属性公开的名为testValue的私有字段testValue

But GetField() doesn't deal with inheritance for nonpublic members, so see GetFields of derived type . 但是GetField()不处理非公共成员的继承,因此请参见派生类型的GetFields This method will help with that: 此方法将帮助您:

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;
}

You can retrieve the field info for the Test class and use it to set the value on the derived class instance like so: 您可以检索Test类的字段信息,并使用它来设置派生类实例上的值,如下所示:

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

You cannot set a value on property without a "setter". 没有“设置者”,就无法为属性设置值。

If you don't want the property to be overridden by some other object outside the scope, you might use "private set" as setter, then you may set the value within the scope. 如果您不希望该属性被范围外的其他对象覆盖,则可以使用“ private set”作为设置器,然后可以在范围内设置值。

Another approach would be to write a method to set the value of the getter of your property. 另一种方法是编写一种方法来设置属性的getter值。 ie

 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