Resolution Circular References for Objects Implementation of ISerializable

I am writing my own implementation of IFormatter, and I cannot think of a way to solve circular references between two types that implement ISerializable.

Here's a regular template:

[Serializable]
class Foo : ISerializable
{
    private Bar m_bar;

    public Foo(Bar bar)
    {
        m_bar = bar;
        m_bar.Foo = this;
    }

    public Bar Bar
    {
        get { return m_bar; }
    }

    protected Foo(SerializationInfo info, StreamingContext context)
    {
        m_bar = (Bar)info.GetValue("1", typeof(Bar));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("1", m_bar);
    }
}

[Serializable]
class Bar : ISerializable
{
    private Foo m_foo;

    public Foo Foo
    {
        get { return m_foo; }
        set { m_foo = value; }
    }

    public Bar()
    { }

    protected Bar(SerializationInfo info, StreamingContext context)
    {
        m_foo = (Foo)info.GetValue("1", typeof(Foo));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("1", m_foo);
    }
}

Then I will do the following:

Bar b = new Bar();
Foo f = new Foo(b);
bool equal = ReferenceEquals(b, b.Foo.Bar); // true

// Serialise and deserialise b

equal = ReferenceEquals(b, b.Foo.Bar);

If I use the ready-made BinaryFormatter to serialize and deserialize b, the above test for reference equality returns true, as expected. But I can’t imagine a way to achieve this in my usual IFormatter.

In a non-ISerializable situation, I can simply revise the “pending” fields of the objects using reflection when the target links were resolved. But for objects that implement ISerializable, it is not possible to enter new data using SerializationInfo.

- ?

+3
2

FormatterServices.GetUninitializedObject. , A B, SerializationInfo, :

( (SI,SC) , SerializationInfo a StreamingContext.)

  • . , , , . , A.
  • GetUninitializedObject, ( ) A, (SI,SC).
  • B , .. SerializationInfo ( - A) B (SI,SC).
  • , A. SerializationInfo A (SI,SC). .

GetUninitializedObject - CLR - ​​ . /null.

- (SI,SC) - , . IDeserializationCallback, , , .

ObjectManager ( ) . , , , , , , . , 4, CLR, (SI,SC) ( , ).

, , , . - IObjectReference ( BinaryFormatter, ). , , .

+5

, , , , "" .

:

for each object
    if object seen before
        output tag created for object with a special note as "tag-reference"
    else
        create, store, and output tag for object
        output tag and object

:

while more data
    if reference-tag to existing object
        get object from storage keyed by the tag
    else
        construct instance to deserialize into
        store object in storage keyed by deserialized tag
        deserialize object

, , :

SomeObject obj = new SomeObject();
obj.ReferenceToSomeObject = obj;    <-- reference to itself

. , , , .

0

Source: https://habr.com/ru/post/1742791/


All Articles