C# 为什么格式化程序是二进制格式化程序,它不能';无法正确处理IDeserializationCallback

C# 为什么格式化程序是二进制格式化程序,它不能';无法正确处理IDeserializationCallback,c#,.net,C#,.net,假设我们有以下代码: static void Main(string[] args) { var firstType = new FirstType(new SecondType(2021)); var stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, firstType); stream.P

假设我们有以下代码:

static void Main(string[] args) {
   var firstType = new FirstType(new SecondType(2021));
   
   var stream = new MemoryStream();
   BinaryFormatter formatter = new BinaryFormatter();
   formatter.Serialize(stream, firstType);

   stream.Position = 0;
   var firstTypeReturned = (FirstType)formatter.Deserialize(stream);
   Console.WriteLine(firstTypeReturned.numFromSecondType);
}

[Serializable]
class FirstType : IDeserializationCallback {
   public SecondType secondType;

   public int numFromSecondType = -1;

   public FirstType(SecondType t) {
      secondType = t;
   }

   void IDeserializationCallback.OnDeserialization(Object sender) {
      numFromSecondType = secondType.num;
   }
}

[Serializable]
class SecondType : IDeserializationCallback {
   public int num;
   public SecondType(int num) {
      this.num = num;
   }
   void IDeserializationCallback.OnDeserialization(Object sender) {
      num = 0;
   }
}
产量为2021年

我希望输出为0,因为从我的角度来看,
FirstType
包含一个
SecondType
对象的字段,所以为了成功地反序列化
FirstType
实例,必须先反序列化
SecondType
,然后将反序列化的
SecondType
输入分配给
FirstType
的字段。因为
SecondType
实现了
IDeserializationCallback
,所以
SecondType
在调用
ondesellization
之前不会被视为“反序列化完成”。因此,当
SecondType
被完全反序列化时,其
num
字段为0,然后将此
SecondType
实例传递给
FirstType
,当
FirstType
调用其
ondeseserialization
时,
numFromSecondType
应为0(因为
SecondType.num
应为0)

但它不是这样的,它看起来像是先调用
FirstType
OnDeserialization
方法,然后调用
SecondType
OnDeserialization
方法。但是它不应该是另一种方式吗-
SecondType
OnDeserialization
方法应该首先调用,因为它必须先执行这个方法,然后才被认为是完全“反序列化”的

那么,格式化程序是否愚蠢到不知道调用每个对象的
方法的正确顺序

那么,格式化程序是否愚蠢到不知道调用每个对象的
方法的正确顺序

这不是沉默的问题;顺序未定义-这是因为在使用
BinaryFormatter
时很容易获得循环,因此可以保证的是,各种
IDeserializationCallback
回调将在整个图形的常规反序列化代码之后发生-此处的目的是为了“父”样式对象可以应用与“子”数据相关的任何修正。如果父级和子级都有
IDeserializationCallback
回调,那么:这听起来是个坏主意,但我想您可以在字段中跟踪“完成了吗”(老实说,我不会-我只是从内部对象中删除回调)

那么,格式化程序是否愚蠢到不知道调用每个对象的
方法的正确顺序


这不是沉默的问题;顺序未定义-这是因为在使用
BinaryFormatter
时很容易获得循环,因此可以保证的是,各种
IDeserializationCallback
回调将在整个图形的常规反序列化代码之后发生-此处的目的是为了“父”样式对象可以应用与“子”数据相关的任何修正。如果父对象和子对象都有
IDeserializationCallback
回调,那么:这听起来是个坏主意,但我想你可以在一个字段中跟踪“完成了吗”(老实说,我不会-我只是从内部对象中删除回调)。

老实说:
BinaryFormatter
被认为是过时的,不推荐的,极其危险,;您确定要在此处使用
BinaryFormatter
吗?如果您真的这样做了,那么可能值得我们尝试找出答案,但是:在这里选择任何其他序列化程序可能是更好的选择。From:“指示在完成整个对象图的反序列化时通知类”。在调用任何回调之前,对象图被认为是反序列化的。我认为你不能依赖于它们的命名顺序:文档根本没有提到这一点all@amjad其他格式化程序是否可以执行与BinaryFormatter相同或更多的操作并不重要(它们都可以)
BinaryFormatter
不仅仅是过时的,它是危险的,而且会从.NET中完全删除。如果您继续使用它,您每年都会遇到更多的错误,因为它的更多组件将从中完全删除。NET@amjad与其要求像BinaryFormatter那样的东西,不如解释一下真正的问题是什么。在反序列化期间,您希望执行哪种处理?你为什么关心订单?这很重要。也许这是一个编码错误(顺序根本不重要)。也许代码试图处理BinaryFormatter的怪癖——让类型句柄反序列化是个坏主意。其他格式化程序有更好的选择,比如自定义converters@amjad对象A引用对象B,对象B引用对象A;现在,你告诉我:“正确”的回调顺序是什么?(
var b=new b();bar a=new a{b=b};b.A=A;
坦白说:
BinaryFormatter
被认为是过时的、不推荐使用的,而且非常危险;你绝对确定要在这里使用
BinaryFormatter
吗?如果你真的这么做,那么可能值得我们尝试找出答案,但是:选择任何其他序列化程序可能是更好的选择m:“指示在完成整个对象图的反序列化时通知类”。在调用任何回调之前,对象图都被认为是反序列化的。我认为您不能依赖调用它们的顺序:文档根本没有提到这一点all@amjad其他格式化程序是否可以执行与BinaryFormatter相同或更多的操作并不重要(它们都可以).
BinaryFormatter
不仅仅是过时的,它是危险的,而且会从.NET中完全删除。如果您继续使用它,您每年都会遇到更多的错误,因为它的组件会从.NET中完全删除。NET@amjad与其要求像BinaryFormatter这样的东西,不如解释一下真正的问题是什么割让