gpt4 book ai didi

c# - 在 C# 中的二进制反序列化期间更改类型

转载 作者:行者123 更新时间:2023-11-30 14:53:12 24 4
gpt4 key购买 nike

我们公司的解决方案之一使用第三方服务。通信是通过 XML 消息传递完成的。在我们这边,我们根据他们提供给我们的 XML 模式生成要使用的类,并且在某些时候我们将其中一些类型序列化为数据库中的二进制 blob 以供以后使用。

问题出在第 3 方公司将其中一个字段从 bool 值类型更改为整数类型。现在,当我们尝试反序列化已经存在的数据时,我们可以预见到类型转换异常(无法从 bool 值转换为整数)。

我的问题是 - 我们如何使用旧的 bool 类型反序列化数据库中的现有数据以将其转换为新的整数类型?

我已经尝试了很多事情 - 其中包括反射和实现 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);
}
}
}

最佳答案

您可以使用 ISerializable 处理这种情况,但是您需要使用 SerializationInfo.GetEnumerator 遍历反序列化的属性以确定实际从流中读取的数据类型。此外,您需要注意 BinaryFormatter 序列化字段 而不是属性,因此如果您的类使用了 Auto-Implemented Properties那么先前存储在二进制流中的名称将是 name of the backing field不是属性的名称。

例如,假设这是您的原始类(class):

[Serializable]
public class Foo
{
public bool Bar { get; set; }

public Foo() { }
}

现在您想将 Bar 更改为整数。要序列化或反序列化旧的和新的 BinaryFormatter 流,请使用以下 ISerializable 的实现:

[Serializable]
public class Foo : ISerializable
{
public int Bar { get; set; }

public Foo() { }

public Foo(SerializationInfo info, StreamingContext context)
{
var enumerator = info.GetEnumerator();
while (enumerator.MoveNext())
{
var current = enumerator.Current;
Debug.WriteLine(string.Format("{0} of type {1}: {2}", current.Name, current.ObjectType, current.Value));
if (current.Name == "Bar" && current.ObjectType == typeof(int))
{
Bar = (int)current.Value;
}
else if (current.Name == "<Bar>k__BackingField" && current.ObjectType == typeof(bool))
{
var old = (bool)current.Value;
Bar = (old ? 1 : 0); // Or whatever.
}
}
}

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

关于c# - 在 C# 中的二进制反序列化期间更改类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30021070/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com