簡體   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