简体   繁体   English

使用iserializable接口时C#中的版本控制序列化

[英]versioning serialization in c# when using iserializable interface

I have a base class FDObjectBase which inherits from ContentControl, ISerializable, INotifyPropertyChanged. 我有一个基类FDObjectBase,它从ContentControl,ISerializable,INotifyPropertyChanged继承。 Now this class gets de-serialized using the below code logic 现在,使用以下代码逻辑对此类进行反序列化

public FDObjectBase(SerializationInfo info, StreamingContext context) : this()
{
   Left = (double)info.GetValue("Left", typeof(double));
    Top = (double)info.GetValue("Top", typeof(double));
    Height = (double)info.GetValue("Height", typeof(double));
    Width = (double)info.GetValue("Width", typeof(double));
    DesignObjectID = (int)info.GetValue("DesignObjectID", typeof(int));
    ShapeType = (int)info.GetValue("ShapeType", typeof(int));
    Angle = (double)info.GetValue("Angle", typeof(double));
    try
    {
        ObjectType = (ObjectType)info.GetValue("ObjectType", typeof(ObjectType));
        //this.ToolTip = ObjectType.ToString();
    }
    catch { }

    OnDeserialized(new EventArgs());
    //DataObject = (DesignData)info.GetValue("DataObject", typeof(DesignData));
    //this.ToolTip = DataObject.Name + " (" + DataObject.ObjectType.ToString().ToLower() + ")";    

}

This works fine in the application however the issue is that i want the de-serialization process to be backward compatible since as per the requirement changes to the this class must not break the de-serialized data which is stored in the database. 这在应用程序中工作正常,但是问题是我希望反序列化过程向后兼容,因为根据对此类的要求更改,一定不能破坏存储在数据库中的反序列化数据。 The solution which i found for this is to add the [OptionalField] attribute to all the new fields which are added to this class however this has not worked out for me. 我为此找到的解决方案是将[OptionalField]属性添加到添加到此类的所有新字段中,但这对我来说还没有解决。 I am still getting the same exception when i add a new field this class (After adding the new field the deserialization does not happen and the below exception is thrown) 当我在此类中添加新字段时,我仍然遇到相同的异常(添加新字段后,不会发生反序列化,并且会抛出以下异常)

System.Reflection.TargetInvocationException was caught
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeMethodHandle._SerializationInvoke(IRuntimeMethodInfo method, Object target, SignatureStruct& declaringTypeSig, SerializationInfo info, StreamingContext context)
       at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
       at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
       at System.Runtime.Serialization.ObjectManager.DoFixups()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at .SeatManagement.Client.Helpers.Generics.Deserialize[T](String data) in Generics.cs:line 117
  InnerException: System.Runtime.Serialization.SerializationException
       Message=Member 'Test' was not found.
       Source=mscorlib

So i am looking for any suggestions which are in the direction of versioning serialization c# when using iserializable interface so that it does not break even when we add new fields to the class. 因此,我在使用iserializable接口时正在寻找朝着版本化序列化c#方向发展的任何建议,这样即使在向类中添加新字段时它也不会中断。 Thanks in advance for your help. 在此先感谢您的帮助。

Finally i have found a solution to this .. however it does not use the out of the box features which are provided by System.Runtime.Serialization. 最终我找到了解决方案..但是,它没有使用System.Runtime.Serialization提供的开箱即用功能。 I have added a property version on my base class 我在基类上添加了属性版本

private static int VERSION_NUMBER = 1;

which gets serialized along with the other design properties as below. 与其他设计属性一起进行序列化,如下所示。

public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue("Version", VERSION_NUMBER);
    //First Version properties
    info.AddValue("Left", Left);
    info.AddValue("Top", Top);
    info.AddValue("Height", Height);
    info.AddValue("Width", Width);
    info.AddValue("DesignObjectID", DesignObjectID);
    info.AddValue("ShapeType", ShapeType);
    info.AddValue("ObjectType", ObjectType.GetIntValue());
    info.AddValue("Angle", Angle);
    //Second Version Properties
}

Now when i deserialize the string i check the version which is stored in the deserialized string 现在,当我反序列化字符串时,我会检查反序列化字符串中存储的版本

public FDObjectBase(SerializationInfo info, StreamingContext context) : this()
{
    int version = Generics.GetSerializedValue<int>(info, "Version");

    if (version >= 1)
    {
        Left = (double)info.GetValue("Left", typeof(double));
        Top = (double)info.GetValue("Top", typeof(double));
        Height = (double)info.GetValue("Height", typeof(double));
        Width = (double)info.GetValue("Width", typeof(double));
        DesignObjectID = (int)info.GetValue("DesignObjectID", typeof(int));
        ShapeType = (int)info.GetValue("ShapeType", typeof(int));
        Angle = (double)info.GetValue("Angle", typeof(double));
        ObjectType = ((int)info.GetValue("ObjectType", typeof(int))).GetEnumValue<ObjectType>();
    }
    if (version >= 2)
    {
        //Add newly added properties for this version
    }
    else { 
        //Add default values for new properties for this version
    }

    OnDeserialized(new EventArgs());

} 

So now when i add a new property which was not deserialized earlier i just increment the version and add the new properties under the second if statement. 因此,现在当我添加之前未反序列化的新属性时,我只需增加版本并在第二个if语句下添加新属性即可。 This way the information which is stored in the DB is always backward compatible. 这样,存储在数据库中的信息始终向后兼容。 It might not be the best solution but it works perfectly for me. 它可能不是最好的解决方案,但对我来说效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM