【问题标题】:Is implementing ISerializable interface necessary when not implementing any custom serialization/deserialization不实现任何自定义序列化/反序列化时是否需要实现 ISerializable 接口
【发布时间】:2012-01-19 20:59:45
【问题描述】:

我正在查看实现ISerializable 接口的解决方案中的类。它有一个GetObjectData 接口要求的序列化方法。这里没有发生任何自定义序列化,它只是用类的属性名称及其值填充SerializationInfo 对象。

[Serializable]
public class PersonName :ISerializable
{
    [DataMember]
    public string NamePrefix { get; set; }
    [DataMember]
    public string GivenName { get; set; }
    [DataMember]
    public string SurName { get; set; }

    public PersonName(string givenName, string surName, string namePrefix)
    {
        GivenName = givenName;
        SurName = surName;
        NamePrefix = namePrefix;
    }

    public PersonName()
    {
    }

    #region ISerializable Members

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("NamePrefix",NamePrefix);
        info.AddValue("GivenName",GivenName);
        info.AddValue("SurName",SurName);
    }
}

据我所知,从我目前阅读的文档来看,这就是用[Serializable] 属性标记的类无论如何都会发生的情况,并且您可以看到该类没有反序列化构造函数,这就是为什么我要开始研究它的原因。据我所知,不需要将反序列化构造函数添加到类中,该类实际上不需要首先实现ISerializable 接口。对吗?

【问题讨论】:

  • 对。判断的方法是不要在 GetObjectData() 方法中提出任何异常。或者换句话说,需要一些 else 而不仅仅是 info 参数来初始化对象。

标签: c# serialization


【解决方案1】:

该类实际上并不需要首先实现 ISerializable 接口。对吗?

正确。实现ISerializable 是当您需要执行默认序列化行为以外的操作时。 [Serializable] 属性应该足够了。

【讨论】:

    【解决方案2】:

    这毫无意义。

    如果它曾经出于更好的理由实现 ISerializable 是合理的,并且实现更改意味着它不再有用。停止实施它可能是一个重大变化。

    如果他们使用显式实现(void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 而不是 public void GetObjectData(SerializationInfo info, StreamingContext context) 并拥有采用 SerializationInfoStreamingContext 私有的构造函数,那么这将是一个破坏性较小的更改 - 从技术上讲仍然是破坏性更改,但实际上破坏任何实际用途的可能性要小得多。这本身就是将该构造函数设为私有的原因。

    如果类不是密封的,它必须至少是protected,如果派生类也可以序列化,则必须使用它。在这种情况下,停止使用它完全是一个重大更改,因为所有派生类都会被破坏。

    如果您不实现它,然后开始这样做,并且有从它派生的类,它同样会带来重大变化。这可能是先发制人的理由,但老实说,我认为这是 YAGNI 原则的重大失败,除非有非常非常好的理由怀疑它会变得有用。 (通常,如果您要添加一些必要的东西,您可以将所需的任何功能包装在另一个类中,在其上实现它,并拥有该类型的成员,因此现有类仍然可以在没有它的情况下进行序列化)。

    编辑:上面的“必须”是“你必须这样做,否则会有不良影响”的“必须”,而不是“你必须这样做,否则它不会”的“必须” t 编译”。当然,前者比后者更糟糕,因为您有时可能无法做到。

    【讨论】:

      【解决方案3】:

      您不妨始终实现 ISerializable。是的,如果您有很多对象,可能会输入很多内容,但是如果您稍后再引入反序列化器,它就会中断。我认为最好对对象进行版本控制,而不是编写新对象并保留旧对象。

      【讨论】:

      • 实际上,我陷入了在 DDD 中使用聚合根的想法。基本上,如果您的对象继承自另一个可序列化对象,请确保实现 ISerializable 并调用基类 GetObjectData(info, context) 方法及其 ctor(info, context)。否则,您所需要的只是 [Serializable] 属性。
      【解决方案4】:

      实现 Iserializable 可以提高性能,因为不需要使用反射来序列化对象

      【讨论】:

        【解决方案5】:

        需要一个签名构造函数(SerializationInfo 信息,StreamingContext 上下文)。用于反序列化时间。

        【讨论】:

          【解决方案6】:

          我明白了,这个类不需要实现 ISerializable。或者你必须添加一个带有签名的构造函数(SerializationInfo 信息,StreamingContext 上下文): protected PersonName (SerializationInfo info, StreamingContext context){ this.NamePrefix = info.GetString("NamePrefix"); this.SurName = info.GetString("SurName"); this.GivenName = info.GetString("GivenName"); }

          【讨论】:

            猜你喜欢
            • 2021-05-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-05-16
            • 2020-04-14
            • 2014-05-23
            相关资源
            最近更新 更多