【问题标题】:BinaryFormatter tries to serialize a form instead of an objectBinaryFormatter 尝试序列化表单而不是对象
【发布时间】:2017-02-13 23:29:39
【问题描述】:

我有一个看起来像这样的 DTO 类:

[Serializable]
[DataContract()]
public class MyClass : IEntity, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    [DataMember()]
    public int Id { get; set; }

    [DataMember()]
    public string Name { get; set; }
}

我所有的 DTO 类及其属性都具有相同的属性。只有这个类有INotifyPropertyChanged

我还有一个比较 2 个对象(可以是复杂对象图)的通用扩展:

public static bool IsEqual<T>(this T object1, T object2)
{
    byte[] array1 = object1.ToByteArray();
    byte[] array2 = object2.ToByteArray();

    return array1.SequenceEqual(array2);
}

上述方法在整个应用程序中使用,没有任何问题。但是,在这个特定的课程中,我遇到了以下异常:

Assembly 'MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 中的类型'MyProject.MyForm' 未标记为可序列化。

我检查并重新检查了我的代码,但没有任何地方可以将表单传递给扩展程序。

我不想序列化表单。我想序列化一个对象(它是表单本身的一个局部变量,就像我拥有的​​所有其他表单一样)。此外,调试上述扩展显示两个参数的类型相同。

由于这是唯一实现INotifyPropertyChanged 的类,问题可能出在这个接口上吗?

【问题讨论】:

  • 您能否向 MyProject.MyForm 添加一个手动序列化程序,将其标记为可序列化,在手动序列化程序中放置一个断点,然后您可以看到是什么触发了对该对象进行序列化的尝试? (“使用 ISerializable 自定义序列化” - kb4dev.com/tutorial/.net-framework-classes-using-csharp/… - 例如。)
  • 啊,所以可能 MyForm 订阅了属性更改事件,因此出现在事件订阅者的内部列表中,正如 Hans 所说,该列表也被序列化。
  • @HansPassant [NonSerialized] 事件显示编译器错误,它仅对字段声明有效。另外,我只需要在这个类上实现属性更改。通常我的 DTO 真的是 POCO。

标签: c# winforms


【解决方案1】:

BinaryFormatter 还将序列化事件的支持字段。尽管这看起来很奇怪,但这有时确实有效。但如果 Form 对象订阅了事件,则它不是可序列化的类。修复:

  [field:NonSerialized]
  public event PropertyChangedEventHandler PropertyChanged;

在反序列化对象时, 会迫使您考虑如何订阅该事件。没有通用的指导,除了将可序列化的数据保存在 POD 类中而没有任何花里胡哨的东西总是一个好主意。使它们更容易推理和维护,而不会出现严重的版本问题。

【讨论】:

  • 此修复程序有效。就我而言,我永远不会反序列化。我只是序列化对象只是为了将当前对象与原始对象进行比较。
  • 你以后一定会后悔的。例如,您不能使用decimal 作为成员。
猜你喜欢
  • 2014-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 2015-01-15
相关资源
最近更新 更多