Исключение выдается, когда я пытаюсь десериализовать объект самоссылки.
System.Runtime.Serialization.SerializationException: "Объект с идентификатором 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
, код будет успешно выполнен.
Я попытался выяснить, в чем дело, поэтому я создал круговую ссылку, например:
ap = b; bp = a; Serialize (fs, a);
и затем десериализовать, без каких-либо исключений. Таким образом, поддерживается циклическая ссылка.
Похоже, что когда вы используете пользовательский суррогат и пытаетесь десериализовать объект, который имеет сам указатель, будет выдано исключение.
Даже ваш суррогат не был вызван.
Так что не так?