【问题标题】:Using readonly fields in combination with serialization将只读字段与序列化结合使用
【发布时间】:2014-01-27 09:18:16
【问题描述】:

在可序列化类中使用只读字段时,不应序列化(或不需要):如何恢复它们?假设以下代码:

[Serializable]
class SerializableClass
{
    [NonSerialized]    
    private readonly object someLock = new object();

    [OnDeserializing]
    private void restore(StreamingContext sc) 
    {
        // cannot one-time-access readonly fields (like in a 
        // constructor or shortcut like above), too sad...

        // someLock = new object();
    }

    // ...
}

我遇到了一些用于锁定的对象(专门用于锁定)的问题,这些对象始终为private readonly(我认为在序列化表示中没有位置)。作为一种解决方法,我问自己:

  • 这些对象不应该是只读的,以便可以恢复吗?
  • 我是否应该将它们包括在内以进行序列化(只要这些只是一些“空对象”)?

但是对于只读字段的使用可能有更通用的解决方案,例如:

  • 有没有一种方法可以在不丢失字段自动序列化的情况下实现被调用的反序列化构造函数(例如在实现 ISerializable 时)?

非常感谢。

【问题讨论】:

    标签: c# constructor locking deserialization readonly


    【解决方案1】:

    我认为这可以通过在该类中创建无参数构造函数并在那里初始化只读字段而不是内联来获得。

    如果该只读字段的值不同,则无法恢复它。 (只读字段只能在构造函数中设置,之后进行反序列化)。

    添加评论作为回应:

    虽然我不建议这样做,但您可以在 OnDeserializing 方法中使用反射设置只读字段,如果更改策略会花费太多精力:

    typeof(SerializableClass).GetField("someLock", BindingFlags.Instance|BindingFlags.NonPublic).SetValue(this,new object());
    

    【讨论】:

    • 不,情况并非如此,因为反序列化时会绕过构造函数。
    • 您使用的是哪个序列化程序?据我所知,二进制和 DataContract 序列化程序将绕过构造函数。
    • 虽然我不建议这样做,但您可以在 OnDeserializing 方法中使用反射设置只读字段: typeof(SerializableClass) .GetField("someLock" ,BindingFlags.Instance|BindingFlags.NonPublic) .SetValue(这个,新对象());
    • 我现在正在使用二进制序列化引擎(其属性也应该与数据协定序列化程序一起使用)。有替代品吗? (顺便说一句:我看不出自动调用默认构造函数和反序列化字段的意义,只要这可能导致奇怪的对象状态;我更喜欢专用的反序列化构造函数/方法......)
    • XmlSerializer 调用不带参数的构造函数(这是必需的),但它的目的不同并且可能有意义。反射不是必须的黑客。但在这种情况下,我也会避免它。我认为您可能必须更改代码,因为二进制序列化程序调用 GetUninitializedObject 来创建对象,并且在该级别没有允许执行自定义代码的扩展点。
    猜你喜欢
    • 2016-11-24
    • 1970-01-01
    • 2014-06-10
    • 2014-08-28
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多