C# 使用ISerializationSubrogate时反序列化自引用对象时引发异常

C# 使用ISerializationSubrogate时反序列化自引用对象时引发异常,c#,.net,serialization,binaryformatter,binary-serialization,C#,.net,Serialization,Binaryformatter,Binary Serialization,尝试反序列化自引用对象时抛出异常 System.Runtime.Serialization.SerializationException:“链接地址信息中引用了ID为1的对象,但该对象不存在。” 这是我的代码: class MySerializationSurrogate : ISerializationSurrogate { public void GetObjectData(object obj, SerializationInfo info, StreamingContext co

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

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)

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

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

甚至你的代理人也没有打电话

那怎么了


我唯一能做到这一点的方法是使用sentinel手动编码自参考有效载荷:

const string Self=“Self”;
public void GetObjectData(对象对象对象、序列化信息、StreamingContext上下文)
{
var检验=(检验)obj;
信息附加值(“prop”,test.prop);
如果(test.me为null){}
else if(ReferenceEquals(test.me,test))
{
信息增值(“我”,自我);
}
其他的
{
信息增值(“me”,test.me);
}
}
公共对象SetObjectData(对象对象对象、序列化信息、StreamingContext上下文、iUrrogateSelector选择器)
{
var it=info.GetEnumerator();
var检验=(检验)obj;
while(it.MoveNext())
{
开关(it.Name)
{
案例“道具”:
test.prop=(int)it.Value;
打破
案例“我”:
开关(it.Value)
{
当s==Self时的大小写字符串s:
test.me=测试;
打破
案例测试t:
test.me=t;
打破
}
打破
}
}
返回obj;
}

我想运行你的代码,这样我就可以看到与你看到的相同的东西-你有
mySerializationSubrogate
代码吗?另外,我不是想“成为那个人”,但是:我真的,真的,真的建议不要使用
BinaryFormatter
,在任何情况下:
mySerializationSubrogate
位于代码块的顶部,您只需要添加一些导入@MarcGravelMaybe例外信息有点不同,我用谷歌翻译把它翻译成英语;我一定是向下滚动了!看,如果您将代理配置代码从
Read
复制到
Save
,一切正常-这就是这里缺少的吗?是的,它确实有效,谢谢。但为什么会出现这个问题呢?如果不是我的错,
BinaryFormatter
中是否存在错误?但这是怎么回事
BinaryFormatter
在.Net中已经存在这么多年了@维克托12369我不认为这是一个错误;更多的情况是:如果你要承担控制权,你需要承担控制权,这包括自参考数据的问题;这里可能有一种方法可以将
IObjectReference
破解到混合中,这样它就可以迅速地将一些东西放入图形中。。。让我看一眼(编辑:不,也不能让它工作)