首页 > 解决方案 > 不使用 Setter 设置实例的属性

问题描述

假设我有一个类和一个如下所示的接口:

[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 的情况下设置属性?

标签: c#.netreflection

解决方案


自动实现的属性具有名为<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;
}

推荐阅读