Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Using Remote Object Models in .NET : Page 2

.NET supports two types of remote objects (by value and by reference) and three activation models for the later (client-activated, single call, and singleton). Each model and object type has its place. This article explains and contrasts the different models and when to apply them.

Marshaling by Reference
Figure 1: Marshal by reference object. Clients in other app domains interact with marshal by reference objects using a proxy. Clients in the same app domain as the object have a direct reference on the object.
Marshal by reference is by far the more common way to access objects across app domains. When you use marshaling by reference the client accesses the remote object using a proxy (see Figure 1).

Client calls on the proxy are forwarded by the proxy to the actual object. To designate a component for marshaling by reference, the class must derive directly (or have one of its base classes derive) from the class MarshalByRefObject, defined in the System namespace. Objects derived from MarshalByRefObject are bound to the app domain in which they were created and can never leave it. Any static method or member variable on a marshaled by reference class is always accessed directly, and no proxy is involved, because statics are not associated with any particular object. The object's app domain is called the host app domain because it is hosting the object and exposes it to remote clients. I will show you how to set up a host in a future article.

Marshaling by Value
The second remoting option is marshaling an object by value. To marshal by value, .NET must make a copy the object's state, transfer the state to the other app domain, and build a new object based on that state. How does .NET know which parts of the object's state can be marshaled by value and which parts cannot? How does .NET save the state of an existing object and how does it build a new object based on that state? What if the object wants to provide some custom marshaling by value mechanism?

Luckily, .NET already has the infrastructure to handle such issues: serialization. The requirements for marshaling by value and for generic serialization are identical. To marshal an object by value, all .NET has to do is serialize the object to a stream, and deserialize the object in the remote app domain. As a result, to enable marshaling by value, the component must be serializable.

Marshaling by value is considerably easier in .NET than it was with DCOM. (The only way to marshal by value in DCOM was to provide custom marshaling—a daunting task, even for proficient DCOM experts.) The primary use for marshaling by value is to pass a structure as a method parameter. Typically, structures are used as data containers and have no logic associated with them. Structures are very useful as method parameters, but unless a struct is serializable you will not be able to use it as a parameter to a remote call. When marshaling a struct by value to a remote object, you actually get the same semantics as with a local object because value types are by default passed in by value:

[Serializable] public struct MyPoint { public int X; public int Y; } public class RemoteClass : MarshalByRefObject { public void MyMethod(MyPoint point) { point.X++; } }

Changes made to the structure on the server side will not affect the structure on the client side:

//Remote client: MyPoint point; point.X = 1; RemoteClass obj = new RemoteClass(); obj.MyMethod(point); Debug.Assert(point.X == 1);

However, if you pass the structure by reference using the out or ref parameter modifiers, changes made on the remote server side will affect the client's copy of the structure:

public class RemoteClass : MarshalByRefObject { public void MyMethod(ref MyPoint point) { point.X++; } } //Remote client: MyPoint point; point.X = 1; RemoteClass obj = new RemoteClass(); obj.MyMethod(ref point); Debug.Assert(point.X == 2);

The usefulness of marshaling by value for a class instance is marginal because the classic client-server model does not fit well with marshaling by value. Marshaling by value for reference types is useful when the client needs to make frequent calls of short duration to the object, and paying the penalty for marshaling the object state to the client is better then paying the penalty multiple times for marshaling the call to the object and back. Imagine, for example, a distributed image capturing and processing system. You would want the machine capturing the images to do so as fast as it can and you would want to do the processing on a separate machine. The capturing machine can create an image object, have the processing client access it (that would make it copy the image), and process it locally. That said, there is usually a better design solution, such as transferring the image data explicitly as a method parameter. In general, it is often a lot easier to simply marshal to the client a reference to the object, and have the client invoke calls on the object.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date