通过反射设置只读属性值

时间:2017-08-30 08:27:20

标签: c#

我需要修改一个只有“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);

    }
  }
}

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

3 个答案:

答案 0 :(得分:1)

&#34;技巧&#34;您发现依赖于自动实现的属性(string Foo { get; }),这些属性编译为具有支持字段的属性(因此您要查找的成员的名称)。请注意,这非常脆弱,因为生成的成员名称没有记录。但是,嘿,依靠反思来访问一个类型的成员一开始就很脆弱。

您没有自动实施的属性,只需访问属性公开的名为testValue的私有字段。

但是GetField()并不处理非公开成员的继承,所以请参阅GetFields of derived type。这种方法有助于:

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

答案 1 :(得分:0)

您可以检索.theList | [ .[map(.id)|indices(2,4)[]] ] 类的字段信息,并使用它来设置派生类实例上的值,如下所示:

Test

答案 2 :(得分:0)

如果没有“setter”,则无法在属性上设置值。

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

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

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

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