Section 10.2. Remote Object Types


10.2. Remote Object Types

If the referenced object is in the same app domain as the client, usually no proxies are involved, and the client will hold a direct reference to the object. The question is, what happens when you try to call methods on a remote object in another app domain? By default, objects are not accessible from outside their own app domains, even if the call is made from another app domain in the same process. The rationale behind this decision is that .NET must first enforce app domain isolation and security. If you intend your objects to be accessed from outside their app domains, you must allow this explicitly in your design and class definition. .NET provides two options for accessing an object across an app domain boundary: by value or by reference. Accessing an object by value means that when a client in App Domain 2 calls a method on an object in App Domain 1, the object is first copied to App Domain 2, so the client gets its own cloned copy of the object. Once a copy is transferred to the remote client, the two objects are distinct and can change state independently. Any change made to the object's state in App Domain 2 applies only to that local copy, which is completely separate from the original object. This is often referred to as marshaling by value and is similar to the analogous behavior in COM. The second way to access a remote object is by reference. In this case, the remote clients hold only a reference to the object, in the form of a proxy. Access by reference is often referred to as marshaling by reference (which was the standard behavior provided by COM).

10.2.1. Marshaling by Value

When an object is marshaled by value, .NET must make a copy of the object's state, transfer the state to the calling app domain, and build up a new object based on that state. There are some difficulties, however. .NET needs to know which parts of the object's state can be marshaled by value and which parts can't. .NET has to obtain the state of an existing object and then build a new object based on that state. And what if the object also 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. As explained in Chapter 9, serializable components can either use the Serializable attribute or implement the ISerializable interface for custom serialization. For example, consider the following class definition:

     [Serializable]     public class MyClass     {        public int Number;     } 

Suppose an instance of this class has 3 as the value of the Number member and is accessed across an app domain boundary by a remote client. .NET marshals the object by value and gives the remote client a copy of the object. Immediately after marshaling, the cloned object has 3 as the value of the Number member (see Figure 10-5). When the remote client in App Domain 3 assigns the value 4 to Number, this assignment affects only its own new and distinct copy. Marshaling by value works across any app domain boundary, be it in the same process or across machines.

The primary use for marshaling by value is when you want 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 can't use it as a parameter to a remote call.

When you marshal 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     { 

Figure 10-5. Marshaling by value


        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 don't 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); 

This is the same as when you pass a structure by reference in the local case.

The usefulness of marshaling a class instance by value is marginal, because the classic client/server model doesn't fit well with marshaling by value. Marshaling by value for reference types is provided for 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 more efficient than 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 want the machine capturing the images to do so as fast as it can, and you want the processing to be done on a separate machine. The capturing machine can create an image object, then have the processing client access the object (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's often a lot easier to simply marshal a reference to the object to the client and have the client invoke calls on the object via a proxy, as described next.

10.2.2. Marshaling by Reference

The second remoting option is marshal by reference, and it's by far the more common way to access objects across app domains. As explained previously, when marshaling by reference is employed, the client accesses the remote object using a proxy (see Figure 10-3). The proxy forwards calls made on it 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 for life to the app domain in which they were created and can never leave it.

Examine Example 10-2 again. The client has a reference to a proxy, which forwards the call to TRaceAppDomain( ) to the new app domain; this is why it traces the remote app domain's name. If the remote object is serializable in addition to being derived from MarshalByRefObject, you can use serialization to persist the object's state, but the object is still accessed by reference. Any static method or member variable on a marshaled-by-reference class is always accessed directly; no proxy is involved, because statics aren't associated with any particular object.

.NET does allow the client app domain and the host app domain to be the same app domain. In that case, the client can still interact with the marshaled-by-reference object using a proxy, even though both share the same app domain. Clients may want to do that in order to activate the object in different ways. However, short-circuiting remoting this way is an esoteric case. In the vast majority of cases, deriving from MarshalByRefObject has no bearing on intra-app domain calls, and clients in the same app domains get direct references to the object.




Programming. NET Components
Programming .NET Components, 2nd Edition
ISBN: 0596102070
EAN: 2147483647
Year: 2003
Pages: 145
Authors: Juval Lowy

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net