[quoted text, click to view] alex wrote:
> I need to send an object of HttpListenerContext class to another
> AppDomain.
Why? That would be my first question. There's something very unintuitive
about one AppDomain creating this object and another one using it.
[quoted text, click to view] > HttpListenerContext class is neither inheritor of
> MarshalByRefObject nor marked as Serializable (more over it is sealed).
> I wrote a wrapper for this class and tried to send an object of this
> class which inherits MarshlByRefObject to another AppDomain:
>
> public class web_request_parameters : MarshalByRefObject
> {
> private readonly HttpListenerContext context_;
>
> public HttpListenerContext context
> {
> get { return this.context_; }
> }
>
> public web_request_parameters( HttpListenerContext context )
> {
> this.context_ = context;
> }
> }
>
> Object is successfully passed through AppDomain boundaries but when I
> try to access the "context" property of this class I get an Exception
> "Type 'System.Net.HttpListenerContext' in Assembly 'System,
> Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is
> not marked as serializable."
>
The reason this doesn't work is simple: while web_request_parameters is a
MarshalByRefObject (and thus lives only in its originating AppDomain) the
system still has to marshal the HttpListenerContext object itself when it's
accessed, and this of course fails for the same reason that passing it
directly fails. In other words, the wrapper isn't wrapping at all.
[quoted text, click to view] > So my question is: should all members of the class which inherits
> MarshalByRefObject be either Serializable or inherit MarshalByRefObject?
Not exactly.
A class which is serializable can control its own serialization by
implementing ISerializable, so it can decide to serialize its parts however
it chooses -- they needn't be serializable themselves. However, if it
doesn't do this and it relies on default serialization, then all fields not
marked [NonSerialized] must be serializable themselves. (All
MarshalByRefObjects are serializable; they serialize by passing proxies.)
For MarshalByRefObject, there's the exception that, obviously, a member need
not be marshallable if it's never accessed from another AppDomain.
Otherwise, it needs to be serializable just as if it had been used directly.
Method calls are remotable as long as their parameters and results are (and
the getters and setters of properties are just special methods).
[quoted text, click to view] > May be there are some workarounds this work?
>
Well, the "workaround" (I'd call it the proper approach, rather) is to keep
the HttpListenerContext in its own AppDomain, so that only that AppDomain is
responsible for it. This is why AppDomains exist in the first place: to
provide a clean separation.
That's not to say it's hopeless. You can use an MBRO as a proxy to marshal
request and results back and forth -- that is, don't try to use an
HttpListenerContext directly in a cross-domain context, instead call methods
and pass simpler types on your proxy (which in turn delegates to the
HttpListenerContext) to achieve what you want.
Working with AppDomains can be tricky. It's a good idea to exactly define
the minimal interfaces you want to communicate with. Don't simply do
cross-AppDomain calls willy-nilly, because the overhead is considerable
(it's essentially just a local form of remoting) and as you've experienced
it's easy to run into problems with nonserializable types. You also lose the
benefits of AppDomains somewhat (clean separation and unloading
capabilities) if you start migrating a lot of data across them.
--