强制公共设置

本文关键字:设置 | 更新日期: 2023-09-27 17:52:46

我最近遇到了一个序列化错误,在我测试的3台机器中只有1台出现了这个错误。

Unable to generate a temporary class (result=1)
error CS0200: Property or indexer 'XXX' cannot be assigned to -- it is read only

通过从我的viewModel中的以下行删除'private'很容易修复:

public ObservableCollection<Contact> Recipients { get; private set; }

我可以加上注释:

// get and set must be public to avoid Serialization errors

但是我更喜欢通过代码强制setter是公共的,因为当代码重构时,注释经常被忘记。如果未来的开发人员将setter更改回private,我希望出现编译错误。

我尝试使用[DataContract] &[DataMember]属性,希望它们能强制公共setter。

有可能吗?

强制公共设置

您可以通过以下方式检查类型的所有属性是否可读可写:

var t = typeof (SomeClass).GetProperties().All(s => s.CanRead && s.CanWrite);

然后使用Contract来检查您的谓词是否实际匹配。你也可以在测试中使用Debug.Assert。我很确定你实际上不能导致编译器错误,因为有人改变访问器上的属性在飞行,所以这将是最接近的你可以得到。

强制类公开特定成员public的唯一方法是通过接口或类。在这种情况下,您可以创建一个简单的接口,其中包含序列化所需的public成员。

public interface IMyClassSerialization
{
 ObservableCollection<Conctact> Recipients {get; set}
}

您的类可以反过来实现这个接口,这将使它抵抗重构,并确保您的序列化属性始终可用。

除非你有一个抽象属性的基类或定义它们的接口,否则我不认为你可以从语法本身强制setter可见性。甚至这种方法也可能有问题,因为它迫使您将问题转移到您的可序列化类上:您如何确保祖先已经声明了其继承者声明的所有setter ?

// at first
public interface IHasProperty
{
    string prop1 {get; set;}
}
public class SerializableClass: IHasProperty
{
    public string prop1 {get; set;}
}
// but then you change SerializableClass
public class SerializableClass: IHasProperty
{
    public string prop1 {get; set;}
    public string prop2 {get; private set;} // oops
}

您可以使用一些额外的工具来确保代码遵循约束(例如使用FxCop自定义规则)。您还可以在测试期间检查所有属性(或选定的属性)是否具有公共设置器。甚至可以在启动时这样做,但我不建议这样做,这种情况应该尽快失败,理想情况下是在测试中,以便向开发人员提供快速反馈