C# 为版本控制实现ISerializable

C# 为版本控制实现ISerializable,c#,.net,version-control,versioning,C#,.net,Version Control,Versioning,考虑以下POD类型的类: public class Price { public decimal OfferPrice { get; set; } } 此类中的对象是从服务器检索的,所以让我们用Serializable来修饰它 [Serializable] public class Price { public decimal OfferPrice { get; set; } } 现在有两个客户端在不同的机器上检索这些对象。他们不会报价格。他们都有一份普莱斯的汇编 现在,这个类用BonuPr

考虑以下POD类型的类:

public class Price { public decimal OfferPrice { get; set; } }
此类中的对象是从服务器检索的,所以让我们用Serializable来修饰它

[Serializable]
public class Price { public decimal OfferPrice { get; set; } }
现在有两个客户端在不同的机器上检索这些对象。他们不会报价格。他们都有一份普莱斯的汇编

现在,这个类用BonuPrice扩展

[Serializable]
public class Price { 
  public decimal OfferPrice { get; set; } 
  public decimal BonusPrice { get; set; } 
}
新程序集部署到服务器,部署到其中一个客户端,但不部署到另一个客户端。 因此,旧版本的客户端在(反)序列化Price对象时将崩溃

旧版本的客户机不需要BonusPrice字段,因此当存在版本差异时,它可以继续工作。 因此,我从一开始就考虑实现ISerializable,因此第一个和第二个版本如下所示:

// version 1.0
[Serializable]
public class Price : ISerializable {
  protected Price(SerializationInfo info, StreamingContext context) {
    OfferPrice = info.GetDecimal("op");
  }

  [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
  public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
    info.AddValue("op", OfferPrice);
  }
}

// version 2.0
[Serializable]
public class Price : ISerializable {
  protected Price(SerializationInfo info, StreamingContext context) {
    OfferPrice = info.GetDecimal("op");
    BonusPrice = info.GetDecimal("bp");
  }

  [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
  public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
    info.AddValue("op", OfferPrice);
    info.AddValue("bp", BonusPrice);
  }
}
因此,现在当一个客户端没有更新到版本2时,它仍将继续只反序列化OfferPrice,而不会崩溃。当它在某个点更新时,它将自动使用BonuPrice

我的问题:当只读取对象时,实现ISerializable是否是版本控制的好方法? 这些问题通常是如何解决的?

您可以使用来控制
BinaryFormatter
SoapFormatter
的版本控制

OptionalFieldAttribute具有VersionAdded属性。在.NET Framework的2.0版中,未使用此选项。但是,正确设置此属性非常重要,以确保该类型与将来的序列化引擎兼容

该属性指示给定字段所属类型的版本 补充。它应该每增加一次(从2开始) 修改类型的时间

还有其他方法,如序列化回调、SerializationBinder、
ISerializable


有关更多信息,请参阅。

在我看来,您试图在一份合同中混合使用两个协议版本。在您的示例中,它是有效的,但在实践中,通常很难统一新协议,所以最好将它们分开。换句话说,您的服务器必须独立支持这两个版本。请看一个好问题,正如我在回答中提到的,您可以使用
OptionalFieldAttribute
我从来没有使用过它,因为当我知道类似的东西存在时已经太晚了。FWIW我使用了
ISerializable
来控制我项目中的版本控制。这当然更容易。因此,如果CLR无法通过反射找到这些字段并且没有引发异常,则不会序列化这些字段?@ServéLaurijssen Yes序列化程序在数据丢失时不会引发异常(它只会忽略),反之亦然。