Okay, I've implemented a fix, and it was really difficult to do so. My
original plan of just flattening out the array didn't work for all
error cases, so in case anyone has to touch the serialization code
again, here's the full story:
I actually had to fix two issues in the serialization code. The first
one was to avoid the delegate serialization bug, but in the course of
doing so, I found that there was also a problem with direct self
references, probably related to the fact that DP 2 implements
IObjectReference. The exception message I kept getting was "The object
with ID 7 implements the IObjectReference interface for which all
dependencies cannot be resolved."
Strangely, indirect self references (i.e. the proxy having a member
holding an object holding a reference back to the proxy) did work -
the .NET serialization engine apparently can handle, and performs a
"fixup" stage at the end of the deserialization process, where all
indirect self references are set to the correct values.
Investigating this, I found that the serialization engine also
performs fixups on delegates held indirectly by the proxy, but
apparently it forgets to do those fixups on directly held delegates.
This bug also occurs when the delegates are held in an object[] and
then even has effects on array elements completely unrelated to the
delegate. This is the bug I originally reported on MS Connect.
Therefore, my fix is actually quite simple:
- In the serialization process for class proxies, don't serialize the
members array directly, but add an "Indirection" object holding the
members array. This causes the fixups to be correctly applied to self
references and delegate members later on, because all members are now
serialized indirectly.
- When deserializing a class proxy, don't immediately populate the
class proxy's members in the constructor, because at this point of
time, no fixups have been performed. Instead, keep the "Indirection"
object for later.
- Make use of IDeserializationCallback (I implemented it on
ProxyObjectReference) and populate the class proxy's base members from
the callback method from the members indirectly held by the
"Indirection" object. At this point of time all fixups have been
performed and everything seems to work fine.
The patch is attached. All the preexisting tests are green (ignoring
the failing PEVerify stuff), and I've added a few additional ones. In
order to simplify the existing serialization code, I've added a
ProxySerializer helper class, which is called from the generated proxy
code and does all the serialization code which was previously directly
emitted into the proxy's GetObjectData() method.
Best regards,
Fabian