C# 通过反射设置只读属性值

C# 通过反射设置只读属性值,c#,C#,我需要修改一个只有“get”选项的属性值。我发现了一些使用GetField的技巧,但没有成功 请参见下面的代码: namespace ConsoleApplication1 { abstract class Test { private int testValue; protected int TestValue { get { return testValue; } } } class Myclass : Test { pub

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

    }
  }
}
命名空间控制台应用程序1
{
抽象类测试
{
私有int测试值;
受保护的int测试值{
获取{return testValue;}
}
}
类Myclass:测试
{
公共Myclass():基(){}
}  
班级计划
{
静态void Main(字符串[]参数)
{
Myclass测试=新的Myclass();
var field=typeof(Myclass).GetField(“k_ubackingfield”,BindingFlags.NonPublic | BindingFlags.Instance);
字段设置值(测试,3);
}
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    public void SetValue(int value) { this.testValue=value; }
  }  
您发现的“技巧”依赖于自动实现的属性(
string Foo{get;}
),这些属性编译成一个带有备份字段的属性(因此就是您正在查找的成员的名称)。请注意,这是非常脆弱的,因为生成的成员名称没有文档记录。但是,依赖反射来访问类型的成员一开始就很脆弱

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

但是
GetField()
不处理非公共成员的继承,请参阅。此方法将有助于:

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;
}
您发现的“技巧”依赖于自动实现的属性(
string Foo{get;}
),这些属性编译成一个带有备份字段的属性(因此就是您正在查找的成员的名称)。请注意,这是非常脆弱的,因为生成的成员名称没有文档记录。但是,依赖反射来访问类型的成员一开始就很脆弱

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

但是
GetField()
不处理非公共成员的继承,请参阅。此方法将有助于:

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

显而易见的问题是。。。为什么?是的,您可以通过获取字段(检查绑定标志和确切名称)来完成此操作,但这是一个令人讨厌的实现细节,可能会随着下一次构建而改变!你拥有那个密码吗?把塞特公之于众。你没有那个密码?张贴一个问题,询问如何避免这种情况(当然,要有一个相关的例子)。顺便说一句,这就是假设代码的问题……在您的示例中,它是
testValue
而不是
k_BackingField
难道您不能为原型添加一个setter,然后删除它吗?可能重复“it is not working”-阅读并解释它到底是如何不起作用的,以及您试图让它起作用的原因。@SpacemanSpiff不,这根本不是这里要问的问题。显而易见的问题是。。。为什么?是的,您可以通过获取字段(检查绑定标志和确切名称)来完成此操作,但这是一个令人讨厌的实现细节,可能会随着下一次构建而改变!你拥有那个密码吗?把塞特公之于众。你没有那个密码?张贴一个问题,询问如何避免这种情况(当然,要有一个相关的例子)。顺便说一句,这就是假设代码的问题……在您的示例中,它是
testValue
而不是
k_BackingField
难道您不能为原型添加一个setter,然后删除它吗?可能重复“it is not working”-阅读并解释它到底是如何不起作用的,以及您试图让它起作用的原因。@SpacemanSpiff不,这根本不是这里要问的问题。您可以通过反思来设置值。您可以在不使用
设置器的情况下设置值,例如,使用构造函数查看问题中的代码,除了一个小错误之外,他们几乎可以这样做。此外,如果有人指出你错了,那么去那个人的个人资料,对他们的随机答案投反对票是一件非常幼稚的事情。如果没有setter(我指的是TestValue),就不能设置属性。当然,您可以设置变量testValue。-这告诉我,在否决某人之前,请仔细阅读。非编译代码和说明错误事实的答案绝对值得否决。你可以,通过反思。你可以在不使用
设置器的情况下设置值,例如,通过构造函数查看问题中的代码,除了一个小错误之外,他们几乎可以这样做。此外,如果有人指出你错了,那么去那个人的个人资料,对他们的随机答案投反对票是一件非常幼稚的事情。如果没有setter(我指的是TestValue),就不能设置属性。当然,您可以设置变量testValue。-这告诉我,在否决某人之前,请仔细阅读。非编译代码和说明错误事实的答案绝对值得否决。感谢提示,它可以工作,但如果我只有一个“Get”属性,而没有任何字段,它就不起作用。你有什么解决办法吗?例如,在我的例子中,我只保护int