使用反射更改只读属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用反射更改只读属性相关的知识,希望对你有一定的参考价值。

可能吗?用反射或任何其他方式?

答案

正如其他人所述,如果您需要这样做,那么您将面临一个设计问题。现在,如果你想知道它是否可能只是为了知道,或者世界上没有其他方法可以做到这一点,那么在一个非常小的helper library和一个扩展方法的帮助下,它确实是可能的。

请考虑以下代码:

class Person {

    int age;
    string name;

    public int Age { get { return age; } }
    public string Name { get { return name; } }
}

// ...

using Mono.Reflection;
using System.Reflection;

// ...

Person person = new Person (27, "jb");
PropertyInfo nameProperty = typeof (Person).GetProperty ("Name");
FieldInfo nameField = nameProperty.GetBackingField ();
nameField.SetValue (person, "jbe");

使用此代码,您可以仅使用属性获取属性的支持字段,并为支持字段分配新值。您可以阅读有关implementation的更多详细信息。

另请注意,它仅适用于简单属性,例如:

public int Age { get { return age; } }

public string Name {
    get { return name; }
    set { name = value; }
}

public double Velocity { get; private set; }

如果您具有自定义代码的复杂属性,则后备字段解析程序将失败。

另一答案

作为自动生成的只读属性的一个非常脏的解决方法:

class MyTestClass
{
    public string MyProperty { get; }

    public MyTestClass( string MyProperty )
    {
        this.MyProperty = MyProperty;
    }
}

您可以通过以下方式修改自动生成的支持字段:

MyTestClass MyClass = new MyTestClass( "Hello" );
FieldInfo MyWriteableField = MyClass.GetType().GetRuntimeFields().Where( a => Regex.IsMatch( a.Name, $"\A<{nameof( MyClass.MyProperty )}>k__BackingField\Z" ) ).FirstOrDefault();
MyWriteableField.SetValue( MyClass, "Another new value" );

PS:当您使用.NET版本<4.6时,您可能需要更改一些代码才能工作。请享用!

另一答案

Simon Mattes的替代方案是

假设你有:

public class MyClass
{
     public int MyNumber {get;}
}

如果用于测试目的,你可以这样做:

var field = typeof(MyClass).GetField("<MyNumber>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(anIstanceOfMyClass, 3);
另一答案

这取决于财产。如果它是一个计算属性 - 不,除非你知道它的基础。如果它只是私有字段的访问者,那么您可以尝试修改该字段。

但总的来说,这是一个非常糟糕的主意,因为你可能不知道这将导致什么副作用。

另一答案
PropertyInfo isReadOnly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance| BindingFlags.NonPublic);
//Remove the readonly property
isReadOnly.SetValue(param, false, null);

//.............put your code here.....

// Set readonly property
isReadOnly.SetValue(param, true, null);

以上是关于使用反射更改只读属性的主要内容,如果未能解决你的问题,请参考以下文章

win7 文件夹为啥只读属性不能更改

公司共享文件夹如何设置某个文件夹只读属性,不可更改复制删除等操作?

java 反射代码片段

在设计时刷新属性网格,当只读集合在 .Net、Winforms 中更改时

如何更改通过反射 C# 获取的属性值

如何在 Vs Code 中更改默认自动选择的用户片段行为