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