【问题标题】:Binary Formatter and properties with\without backing fields带有\不带支持字段的二进制格式化程序和属性
【发布时间】:2015-04-16 13:42:22
【问题描述】:

我使用 BinaryFormatter 将以下类序列化为一个文件:

[Serializable]
public class TestClass
{
    public String ItemTwo { get; set; }
    public String ItemOne { get; set; }
}

使用此代码:

FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, new TestClass{ItemOne = "ItemOne", ItemTwo = "ItemTwo"});
fs.Close();

使用此代码反序列化时:

FileStream fs = new FileStream("DataFile.dat", FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();
TestClass addresses = (TestClass)formatter.Deserialize(fs);
fs.Close();

我一切正常。 但是,现在我需要该类具有一些支持字段,如下所示:

[Serializable]
public class TestClass
{
    private string _itemTwo;
    private string _itemOne;

    public String ItemTwo
    {
        get { return _itemTwo; }
        set { _itemTwo = value; }
    }

    public String ItemOne
    {
        get { return _itemOne; }
        set { _itemOne = value; }
    }
}

我的问题是,由于某种原因,以前版本的反序列化不再起作用。我得到了类,但属性保留为空。
我不能影响序列化过程或以前的类状态。
如何让文件反序列化为当前类?

【问题讨论】:

  • 我试过你的代码,它工作正常。 BinaryFormatter 不会序列化私有字段,但它会序列化带有支持字段的属性。您使用的是哪个版本的 .NET?
  • 二进制格式化程序不兼容版本。如果没有旧的 dll,您将无法使用。将新旧 .dll 文件加载到新项目中并编写转换器程序。或者也许 ildasm 旧的 dll 来获取它给支持字段的名称。
  • @GiovanniCampo 我正在使用 4.5。我们有一个现实生活中的问题,我创建了一个小程序来模拟它,但它也不起作用。
  • @RadioSpace 所以如果我找到支持字段并将其添加到类中它应该可以工作吗?
  • 显式声明支持字段与否无关紧要。如果你不这样做,那么编译器会自动生成一个。但是,您获得与该类以前版本的二进制兼容性的可能性是 zippo。您需要保留原始程序集,以便仍然可以使用旧类定义反序列化旧数据。如果您的新课程发生了很大变化以仍然保持旧数据可用,那么您将遇到无法解决的问题。

标签: c# properties deserialization binaryformatter backing-field


【解决方案1】:

如果您尝试序列化TestClass 的第一个版本,则二进制格式化程序将自动序列化后域。自动属性只是语法糖,编译器将它们转换为带有支持字段的普通属性。例如,如果您使用 ILSpy 反编译原始控制台应用程序(或类库),您会看到您的私有字段被声明为:

.field private string '<ItemOne>k__BackingField'

这与您的第二个声明有很大不同,其支持字段为:

.field private string _itemOne

一种方法是在TestClass 上声明ISerializable 接口,并使用SerializationInfo 类中包含的信息获取原始属性的值

[Serializable]
public class TestClass : ISerializable
{
    private string _itemTwo;
    private string _itemOne;

    public String ItemTwo
    {
        get { return _itemTwo; }
        set { _itemTwo = value; }
    }

    public String ItemOne
    {
        get { return _itemOne; }
        set { _itemOne = value; }
    }

    protected TestClass(SerializationInfo info, StreamingContext context)
    {
        _itemTwo = info.GetString("<ItemTwo>k__BackingField");
        _itemOne = info.GetString("<ItemOne>k__BackingField");
    }

    [SecurityPermissionAttribute(SecurityAction.Demand,
    SerializationFormatter = true)]
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        //Add data to your serialization process here
    }
}

所以你告诉BinaryFormatter 你希望在反序列化期间如何初始化你的支持字段。

【讨论】:

  • 我认为如果您查看后端应该有一种方法。摆脱困境的好方法
猜你喜欢
  • 2015-06-22
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
  • 1970-01-01
  • 1970-01-01
  • 2012-09-05
  • 1970-01-01
相关资源
最近更新 更多