TL;DR;
My custom [Serializable] class overrides GetHashCode and Equals, so multiple distinct objects can be "equal", and it looks like BinaryFormatter calls OnSerialized only once, but calls OnDeserialized twice when two equal but distinct (ReferenceEquals == false) objects exist in the graph.
What can I do to ensure that for every call to [OnSerialized] method [OnDeserialized] method is called exactly once provided I want to keep my GetHashCode and Equals implementations?
Ideally, I would like to instruct BinaryFormatter to use my custom implementation of IEqualityComparer for my custom class so that it would not try to "merge" distinct but equal instances.
Background
The class wraps a refcounted unmanaged handle, that is passed across app domains using BinaryFormatter. To keep the refcount in sync with alive .NET instances, I increase it by 1 in [OnSerialized] handler, assuming the object will be deserialized exactly once, which is violated in the scenario above (the serialized bits are discarded after deserialization).
Implementing
ISerializableinstead of using[OnSerialized]attribute works:GetObjectDatagets called for each distinct object even if they are equal byEquals+GetHashCode.Downsides are:
.ctor(SerializationInfo info, StreamingContext context)