none
Problems serializing a MarshalByRefObject-derived class instance RRS feed

  • Question

  • I hope this is the right forum, I haven't posted in a while and MSDN seems to be a mess now.

    I have a very complex project, with multiple processes communicating with each other using various forms of IPC. There is one class, derived from MarshalByRef and serializable, from which I instantiate objects that I occasionally call remotely (via an IPC channel). Also, once in a while, I need to serialize those (for storage and other purposes). Because of that, the class has a copy constructor implemented (copy eliminates proxies) and I call that before serialization. Now, there is a scenario where I'd like to avoid having to call the copy constructor (circular reference, by design) and I feel I should be able to do that because the object that I want to serialize was created locally and I certainly do not intend to ever call it remotely (in that context), and it, indeed, starts with the __identity field being null. The trouble is that at some point that field's value becomes a ServerIdentity instance and it, thus, cannot be serialized. I have spent days trying to find out where that is occurring but I cannot figure it out.

    The code is way too complex to try and reproduce a small sample that I can post here; I'm mostly hoping that someone would have a general idea of what is going on. I am still working on the possibility to find a way around those circular references preventing me from being able to call the copy constructor (which eliminates the remote proxy), but I might not be able to do that (it's a programming environment). The object instance was created in the same application domain, so the object itself is not a transparent proxy. What could be causing the MarshalByRef.Identity private property to become assigned to ServerIdentity? What does that property mean and do? In my desperation I have even considered nulling that field (if I could access it) or using a surrogate selector to work around the problem, but I know that is ugly and dangerous (plus my object is too complicated to manually serialize). Any idea as to what I could do? Thanks!

    Kamen


    Currently using Visual Studio 2013 U5, native C++ (Windows API) and C# (.Net, WPF), on Windows 7 64-bit; Mountain Time zone.




    • Edited by Kamen Friday, December 4, 2015 4:59 AM
    Friday, December 4, 2015 1:49 AM

Answers

  • I am closing this question because it doesn't really bring much to the table. In my follow-up I already answered the specific questions I had in my original post, and I was able to resolve the issue I had by breaking the circular reference (used a normal constructor that doesn't perpetuate it).

    For those coming here through a search: if an object participates in remoting - either as a server or client - it cannot be serialized. Any tricks, such as disconnecting a proxy or invalidating the lease of a server, will likely break your functionality, so don't even look there. Custom-serializing a server is acceptable but it is probably simpler to just use a copy of that object to serialize, which is, in a way, equivalent. In my case I was using copy-constructors but a recursive design prevented me from using it in a particular case, so I had to use another kind of copy. The reason I had so much trouble finding the problem is because the object had become a remoting server after it was checked for it, and because the reference was nested so deep that it was difficult to find (Note: OzCode seems to be working but it has a ton of issues in my complex scenarios; however, given how many issues Visual Studio itself has, it is probably worth its price.)

    To recap: my issues weren't really related to the technologies (remoting, marshaling), other than their complexity. You just have to careful how you use them.

    Kamen


    Currently using Visual Studio 2013 U5, native C++ (Windows API) and C# (.Net, WPF), on Windows 7 64-bit; Mountain Time zone.

    • Marked as answer by Kamen Thursday, December 10, 2015 6:51 PM
    Thursday, December 10, 2015 6:51 PM

All replies

  • Hi Kamen,
    I am trying to involve someone familiar with this topic to further look at this issue.

    There might be some time delay. Appreciate your patience.

    Best Regards,

    Grady

    Monday, December 7, 2015 5:45 AM
    Moderator
  • Thank you, Grady. If it's too much trouble, don't worry about it. This is a very specialized problem that few other people would run into (or, if they are advanced enough to get into this subject matter, they'd know better than to get themselves into this kind of mess).

    I have learned a few things in mean time. When a MarshalByRefObject is locally instantiated, but has not been accessed remotely, it acts as a normal object, its Identity field is null. If a remote call requests access to it, it becomes a server and the Identity field gets assigned an instance of the "infamous" (to those, like me, who manage to get in trouble for it) System.Runtime.Remoting.ServerIdentity class. It still acts like a normal, local object, but it has that field and, thus - and obviously - cannot be serialized. At the other end, a MarshalByRefObject that has made the remote call would actually have a System.Runtime.Remoting.Proxies.__TransparentProxy assigned to it and that would be all you could see in the QuickWatch.

    I actually found where the remote access occurs and I eliminated it (by making a copy before sending the reference to the remote site), or so I thought because I'm still getting that error and for the life of me, I can't find where that ServerIdentity reference is still residing. I even obtained the very useful tool OzCode and did a search for "ServerIdentity", "proxy", "identity", and anything else I could think of, down to 9 levels deep, but it found nothing suspicious, and certainly no instance of the ServerIdentity class that the binary serializer is complaining that it can't serialize.

    I realize that I should ultimately find a way to make sure a good copy is made before the objects are sent to the remote location, but I've been trying to do that for days. But, mostly, it is good to learn a thing or two about doing those things right (obviously, I have too much invested to make major changes, but still).

    Kamen


    Currently using Visual Studio 2013 U5, native C++ (Windows API) and C# (.NET, WPF), on Windows 7 64-bit; Mountain Time zone.


    • Edited by Kamen Wednesday, December 9, 2015 3:41 AM
    Monday, December 7, 2015 7:57 PM
  • Quick update: using OzCode and drilling 11 levels deep, I was able to find another reference to ServerIdentity. I will see what it'll take to eliminate it.

    Kamen


    Currently using Visual Studio 2013 U5, native C++ (Windows API) and C# (.NET, WPF), on Windows 7 64-bit; Mountain Time zone.
    • Edited by Kamen Wednesday, December 9, 2015 3:41 AM
    Tuesday, December 8, 2015 12:01 AM
  • I am closing this question because it doesn't really bring much to the table. In my follow-up I already answered the specific questions I had in my original post, and I was able to resolve the issue I had by breaking the circular reference (used a normal constructor that doesn't perpetuate it).

    For those coming here through a search: if an object participates in remoting - either as a server or client - it cannot be serialized. Any tricks, such as disconnecting a proxy or invalidating the lease of a server, will likely break your functionality, so don't even look there. Custom-serializing a server is acceptable but it is probably simpler to just use a copy of that object to serialize, which is, in a way, equivalent. In my case I was using copy-constructors but a recursive design prevented me from using it in a particular case, so I had to use another kind of copy. The reason I had so much trouble finding the problem is because the object had become a remoting server after it was checked for it, and because the reference was nested so deep that it was difficult to find (Note: OzCode seems to be working but it has a ton of issues in my complex scenarios; however, given how many issues Visual Studio itself has, it is probably worth its price.)

    To recap: my issues weren't really related to the technologies (remoting, marshaling), other than their complexity. You just have to careful how you use them.

    Kamen


    Currently using Visual Studio 2013 U5, native C++ (Windows API) and C# (.Net, WPF), on Windows 7 64-bit; Mountain Time zone.

    • Marked as answer by Kamen Thursday, December 10, 2015 6:51 PM
    Thursday, December 10, 2015 6:51 PM
  • Hi kamen,

    Thanks for sharing your solution.

    Best Regards,

    Wanjun Dong


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place. Click HERE to participate the survey.

    Friday, December 11, 2015 1:33 AM
    Moderator