使用ISerializationSurrogate反序列化自引用对象时抛出异常

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

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,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),new MySerializationSurrogate());,代码将成功运行。

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

我试图找出问题所在,因此创建了一个循环引用,如下所示:

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

然后反序列化,没有任何例外。因此支持循环引用。

似乎当您使用用户定义的代理并尝试反序列化具有自指针的对象时,将引发异常。

即使您的代理人没有被呼叫。

那怎么了?

zhangyukexin 回答:使用ISerializationSurrogate反序列化自引用对象时抛出异常

我能做得到的唯一方法是使用哨兵手动编码自指有效载荷:

    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,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;
    }
本文链接:https://www.f2er.com/2494502.html

大家都在问