执行公共制定者

时间:2014-03-24 10:00:05

标签: c# serialization

我最近遇到了一个序列化错误,它只出现在我测试的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]&amp; [DataMember]属性希望它们能够强制执行公共设置器。

有可能吗?

3 个答案:

答案 0 :(得分:1)

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

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

然后使用Contract检查您的谓词是否实际匹配。你也可以在测试中Debug.Assert。我相当肯定你实际上可能因为有人动态更改属性上的访问者而导致编译器错误,所以这将是你能得到的最接近的。

答案 1 :(得分:0)

除非你有一个抽象属性的基类或定义它们的接口,否则我认为你不能从语法本身强制对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自定义规则)。您还可以在测试期间检查所有属性(或选定的属性)是否具有公共设置器。它甚至可以在启动时完成,但我不推荐它,这种情况应该尽快失败,理想情况是在测试中以便快速反馈给开发

答案 2 :(得分:0)

您可以通过接口或类来强制实现类以公开特定成员public的唯一方法。在您的情况下,您可以创建一个简单的界面,其中包含您需要公开进行序列化的成员。

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

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