【发布时间】:2015-07-13 07:17:45
【问题描述】:
我们公司的一种解决方案使用了第三方服务。通信是通过 XML 消息传递完成的。最后,我们根据它们提供给我们的 XML 模式生成要使用的类,并在某些时候将其中一些类型序列化为数据库中的二进制 blob 以供以后使用。
问题在于该第 3 方公司已将其中一个字段从布尔类型更改为整数类型。现在,当我们尝试反序列化已经存在的数据时,我们可以预见会遇到类型转换异常(无法从布尔值转换为整数)。
我的问题是 - 我们如何使用旧的布尔类型反序列化数据库中的现有数据以将其转换为新的整数类型?
我尝试了很多方法,其中包括反射和实现 ISerializable,但到目前为止还没有成功。理想的解决方案是实现 ISerializable,但在尝试反序列化现有数据时出现“未找到成员”错误,因为它已经仅使用 Serializable 属性进行了序列化。
欢迎提出任何建议!
编辑:添加一些代码以清楚地展示我的问题。
namespace ClassLibrary
{
[Serializable]
public class Foo //: ISerializable
{
public bool Bar { get; set; }
public Foo() { }
//[OnDeserializing()]
//internal void OnDeserializingMethod(StreamingContext context)
//{
// Bar = 10;
//}
//public Foo(SerializationInfo info, StreamingContext context)
//{
// Bar = (int)info.GetValue("Bar", typeof(int));
//}
//public void GetObjectData(SerializationInfo info, StreamingContext context)
//{
// info.AddValue("Bar", Bar);
//}
}
}
namespace ConsoleApplication2
{
static class Program
{
static void Main(string[] args)
{
Foo foo;
// Run #1, where Foo.Bar is a boolean
foo = new Foo();
foo.Bar = true;
SerializeObject(foo);
byte[] data = File.ReadAllBytes(@".\Test.bin");
foo = DeserializeObject(data) as Foo;
// Now change Foo.Bar to an integer type, comment the lines above, and uncomment the two lines below
//byte[] newData = File.ReadAllBytes(@".\Test.bin");
//foo = DeserializeObject(newData) as Foo;
Console.WriteLine(foo.Bar);
Console.ReadLine();
}
private static Object DeserializeObject(byte[] buff)
{
if (buff == null) return null;
BinaryFormatter formatter = new BinaryFormatter();
formatter.Binder = new CustomSerializationBinder();
MemoryStream ms = new MemoryStream(buff);
return formatter.Deserialize(ms);
}
private static void SerializeObject(Object obj)
{
if (obj == null) return;
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream ms = new FileStream(@".\Test.bin", FileMode.Create))
{
formatter.Serialize(ms, obj);
}
}
}
【问题讨论】:
-
您可以访问以前版本的 DLL 吗?
-
你没有访问权限?
-
字段名称有变化吗?还是他们保持相同的字段名称,只是改变了类型?这很重要,因为从序列化的角度来看,如果他们更改类型并保持相同的字段名称,这将是一个重大更改。理想情况下,他们会添加一个新的“int”字段,而单独留下旧的“bool”字段,并以某种方式将其标记为已弃用。如果他们这样做是一项重大更改,那么我认为您最好的选择是保留两个类的副本......一个用于反序列化旧数据,另一个用于反序列化新数据。
-
您使用的是哪个序列化程序 --
XmlSerializer、DataContractSerializer或其他? -
你不能碰垃圾桶。序列化如果您的数据库现在有东西,您应该将 XML 反序列化到另一个类中 - 即使您无法让您的工具/框架为您执行此操作,您也可以始终以艰难的方式处理它(使用
System.Xml并检查节点手动) - 下次最好将Version字段包含到您的二进制序列化类中,或者不要序列化为 Binary(使用BinaryFormatter或它的名称)
标签: c# serialization blob binaryformatter