在没有 Setter 的情况下设置实例的属性 [重复]
Posted
技术标签:
【中文标题】在没有 Setter 的情况下设置实例的属性 [重复]【英文标题】:Set Property of Instance without Setter [duplicate] 【发布时间】:2021-09-22 00:51:54 【问题描述】:假设我有一个如下所示的类和接口:
[Serializable]
public class MyClass : IClass
public int Prop => 42;
public interface IClass
int Prop get;
如您所见,没有 Setter。但我希望使用反射来改变 Prop 属性,但我似乎做不到。到目前为止,这是我所拥有的:
var property = typeof(MyClass).GetProperty("Prop", BindingFlags.Instance | BindingFlags.Public);
property.SetValue(instaneOfClass, 31);
我不断收到此错误:System.ArgumentException: Property set method not found.
这不应该吗?如何在不使用 setter 的情况下设置属性?
【问题讨论】:
我将其作为先前建议答案的副本关闭,因为它已经包含文本“复杂代码”。我还编辑了答案以添加“复杂代码包括int TheAnswer => 42;
,因此它也清楚地回答了这个问题。
剩下的谜团是:值 '42' 的 int 存储在哪里?
【参考方案1】:
自动实现的属性具有名为 <PropName>k__BackingField
的支持字段。
在您的情况下,您可以像这样访问此支持字段:
var property = typeof(MyClass).GetField("<Prop>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
property.SetValue(instanceOfClass, 31);
请注意,我调用的是GetField()
而不是GetProperty()
,并使用BindingFlags.NonPublic
而不是BindingFlags.Public
,因为支持字段是私有的。
但是,由于这是一个表达式主体成员(lambda 语法),因此不会生成支持字段。 getter 不依赖另一个成员,而是简单地返回给定表达式的结果,并且编译器不需要生成支持字段。
使用显式 getter 实现您的属性将生成一个支持字段,上面的代码将起作用。
public class MyClass : IClass
public int Prop get; = 42;
【讨论】:
【参考方案2】:如果您指定一个 getter,您将拥有一个编译器生成的包含属性名称的字段。然后可以使用反射(GetFields、SetValue)修改该字段的值:
public class Foo
public Foo() => Bar = 42;
public int Bar get;
static void Main()
var f = new Foo();
Console.WriteLine(f.Bar); // ==> 42;
f.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic).First(x => x.Name.Contains("Bar")).SetValue(f, 43);
Console.WriteLine(f.Bar); // ==> 43;
它不适用于您的示例中的计算属性。
【讨论】:
以上是关于在没有 Setter 的情况下设置实例的属性 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 setter 的情况下调试更新 php Trait 的实例变量
属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在哪种情况下用?