【问题标题】:Exception threw out when deserializing self-reference objects while using ISerializationSurrogate使用 ISerializationSurrogate 反序列化自引用对象时抛出异常
【发布时间】:2020-04-07 11:24:25
【问题描述】:

当我尝试反序列化自引用对象时抛出异常。

System.Runtime.Serialization.SerializationException: "链接地址信息中引用了ID为1的对象,但该对象不存在。"

这是我的代码:

class MySerializationSurrogate : ISerializationSurrogate {
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        Console.WriteLine("MySerializationSurrogate.GetObjectData()");
    }
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) {
        Console.WriteLine("MySerializationSurrogate.SetObjectData()");
        var it = info.GetEnumerator();
        while (it.MoveNext()) {
            Console.WriteLine($"{it.ObjectType} {it.Name} {it.Value}");
        }
        return obj;
    }
}

[Serializable]
class Test {
    int prop { get; set; } = 123321;
    Test me { get; set; }
    public Test() { me = this; }
}

class Program {

    static void Save() {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream fs = new FileStream("E:\\a.txt", FileMode.Create);
        Test ch = new Test();
        bf.Serialize(fs, ch);
        fs.Close();
    }

    static void Read() {
        BinaryFormatter bf = new BinaryFormatter();
        SurrogateSelector mss = new SurrogateSelector();
        mss.AddSurrogate(typeof(Test), bf.Context, new MySerializationSurrogate());
        bf.SurrogateSelector = mss;
        FileStream fs = new FileStream("E:\\a.txt", FileMode.Open);
        object ch = bf.Deserialize(fs);
        fs.Close();
    }

    static void Main(string[] args) {
        Save();
        Read();
        Console.ReadLine();
    }
}

我的控制台中没有任何输出,所以我认为 SetObjectData()GetObjectData() 没有被调用。

如果我删除mss.AddSurrogate(typeof(Test), bf.Context, new MySerializationSurrogate());,代码将成功运行。

如果我删除Test.me,代码将成功运行。

我试图找出问题所在,所以我创建了一个这样的循环引用:

a.p=b;b.p=a;序列化(fs,a);

然后反序列化,没有任何异常。所以支持循环引用。

似乎当你使用用户定义的代理并尝试反序列化具有自指针的对象时,会抛出异常。

连你的代理人都没有被召唤。

那怎么了?

【问题讨论】:

  • 我想运行您的代码,这样我就可以看到您所看到的相同内容 - 您有 MySerializationSurrogate 代码吗?另外,我并不是要“成为那个人”,而是:我真的,真的,真的建议反对BinaryFormatter,在任何情况下:blog.marcgravell.com/2020/03/…
  • MySerializationSurrogate 在代码块的顶部,您只需要添加一些导入即可。 @MarcGravell
  • 可能异常信息有点不同,我用谷歌翻译翻译成英文。
  • 哦,原来如此;我一定是向下滚动的!看着
  • 如果您将代理配置代码从Read 复制到Save,一切正常——这就是这里缺少的吗?

标签: c# .net serialization binaryformatter binary-serialization


【解决方案1】:

我可以让它工作的唯一方法是使用哨兵来手动编码自引用有效负载:

    const string Self = "SELF";
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        var test = (Test)obj;
        info.AddValue("prop", test.prop);
        if (test.me is null) { }
        else if (ReferenceEquals(test.me, test))
        {
            info.AddValue("me", Self);
        }
        else
        {

            info.AddValue("me", test.me);
        }


    }
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        var it = info.GetEnumerator();
        var test = (Test)obj;
        while (it.MoveNext())
        {
            switch (it.Name)
            {
                case "prop":
                    test.prop = (int)it.Value;
                    break;
                case "me":
                    switch(it.Value)
                    {
                        case string s when s == Self:
                            test.me = test;
                            break;
                        case Test t:
                            test.me = t;
                            break;
                    }
                    break;
            }
        }
        return obj;
    }

【讨论】:

  • 是的,它确实有效,谢谢。但是为什么会出现这个问题呢?如果不是我的错,BinaryFormatter 是否有 bug?
  • 但这怎么可能呢? BinaryFormatter 在 .Net 中已经存在这么多年了!
  • @victor12369 我不认为这是一个错误;更多的情况是:如果你假设控制,你需要假设控制,这包括自引用数据的问题;可能有一种方法可以将IObjectReference 破解到这里的组合中,以便它可以立即将 something 放入图表中......让我看一下(编辑:不,无法理解工作)
猜你喜欢
  • 1970-01-01
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多