Categories of Remotable Types

Team-Fly    

 
.NET and COM Interoperability Handbook, The
By Alan Gordon
Table of Contents
Chapter Eleven.  .NET Remoting

Categories of Remotable Types

A type that is exposed through .NET remoting is called a remotable type. A remotable type can be either marshal by value, marshal by reference, or context bound. Let's explore how each of these remotable types behaves.

Marshal by Value

A marshal- by-value type is copied from the server app domain to the client app domain when it is first accessed from a client. After the object is copied to the client app domain, all further access on the object is direct, that is, it does not go through a proxy. Because marshal-by value-objects must be copied from one app domain to another through a channel, they must be serializable to a stream. A marshal-by-value object can be made serializable by implementing the ISerializable interface or by decorating its class with the System.Serializable attribute as shown here:

 [Serializable] public class Employee { ... } 

When a marshal-by-value object is passed from one app domain to another, the .NET remoting infrastructure will copy it to the client app domain whether it is passed in as an input parameter, a return value, or an output parameter. When the object is called from a client that resides in the same app domain, no marshaling or copying of the object's state is performed.

Marshal by Reference

Marshal-by-reference objects are objects that always execute in their originating app domain. When you instantiate a marshal-by-reference object, the .NET remoting infrastructure will set up a proxy object in the client app domain. The client will make calls on the object through the proxy, and the proxy will marshal the method call to the host app domain for the object. To create a marshal-by-reference class, you need only to inherit from the System.MarshalByRefObject class as shown here:

 public class Company : MarshalByRefObject { ... } 

The .NET remoting infrastructure will return a proxy to the receiving app domain whenever you pass a marshal-by-reference object between app domains, whether it is passed in as an input parameter, a return value, or an output parameter. In some cases, the client may receive a proxy before the object actually exists in the server app domain. The object will only be created on the server when you make a method call through the proxy. This behavior depends on whether you are using client or server activation. I talk about activation modes shortly.

Context-Bound Objects

Context-bound objects are a special category of marshal-by-reference object. The difference is that the innermost boundary where a proxy is required is a context instead of an app domain. In other words, if a context-bound object and its client reside in different contexts, the client will only be able to access the object through a proxy, even if the client and object reside in the same app domain. A context is an environment in which objects with similar run-time requirements execute. Contexts are usually used to provide services, such as transactions or thread synchronization, for the objects that reside in them. Special interception code is used on a cross-context proxy to implement these system services.

Note

Serviced components , that is, objects that use the .NET Enterprise Services, are the best example of a context-bound object. See the discussion of .NET Enterprise services and COM+ in Chapter 9 to learn more about contexts and interception.


Every app domain has a default context, and, unless you create context-bound objects (such as serviced components), all objects and clients in an app domain will reside in the default context.

To create context-bound object, you need only to inherit from System.ContextBoundObject , which itself inherits from System.MarshalByRef-Object as shown here:

 public class Company : ContextBoundObject { ... } 

In most cases, though, the only context-bound object that you will create is a service component, which must inherit from the System.Enterprise-Services.ServicedComponent class (which inherits from System.ContextBoundObject ) as shown here:

 public class Company : ServicedComponent { ... } 

The .NET remoting infrastructure will return a proxy to the receiving context whenever you pass a context-bound object between contexts, whether it is passed in as an input parameter, a return value, or an output parameter.

Now that you understand the three different types of remotable objects, you're probably wondering which one you should use in a particular situation. If you temporarily consider marshal-by-reference and context-bound objects to be a single category, because their behavior is similar, the real question becomes when should I use a marshal-by-value object and when should I use a marshal-by-reference object? The answer to this question depends on whether, for a given situation, it is better to bring the code to the data or the data to the code.

With a marshal-by-value object, you are essentially copying the state (the data) of your object to the client that is making the request on the object and then executing the code on the client, that is, you are bringing the data to the code. This works best for objects that have a small state or objects that do not have to run on a specific server for reasons of performance, security, or the availability of platform-specific services like COM+ or MSMO. Objects that need to be called many times are also good candidates to be implemented as marshal-by-value objects. If you need to make many calls on an object, it's usually better to copy it to its client and access it from there rather than pay the price of a cross-app-domain (or context) hop each time you make a call. This is true even if the object has a large state. ADO Recordsets are a good example of a marshal-by-value object that potentially can be large.

Marshal-by-reference objects are most useful in situations where it is important for reasons of performance, security, or the availability of platform-specific services that the state (the data) of the object remains on a particular machine. In most cases, a marshal-by-reference object will execute either on the machine where the data that it uses resides or on a machine that is in close proximity to the machine that contains the data. So with a marshal-by-reference object you are taking the code to the data. If an object uses .NET Enterprise services or COM+, it must run on the machine where those services are available. If the object uses a large amount of data or if it is primarily a database object, it is always better for the object to execute in close proximity to its data. Another situation where a marshal-by-reference object makes sense is if an object requires a great deal of processing power. In this case, it is best to make sure that the object executes on a server class machine where you can be sure to have the available processing power.

The choice between a context-bound or a marshal-by-reference object is a little more subtle. Whether you need a context-bound object depends on whether you require runtime services like transactions or thread-synchronization for the object. If not, in most cases, you are better off just using a marshal-by-reference object.

Activation

.NET Remoting gives you a number of activation options when you use marshal-by-reference objects. You can specify two types of server activation or client activation for your objects.

SERVER ACTIVATION

With server activation, the client has no direct control over the life cycle of the objects that the server uses to service requests. The client makes a request on some well-known end point (either a URI or a TCP/IP port), and the server creates objects as needed to service these requests . Server-activated objects are also sometimes called well-known objects. A server-activated object can either be used to service only a single call, that is, the object is created when a request comes in, used to service the request, and then destroyed immediately. It can also be a Singleton, in which case a single instance is used to service all requests. If an instance exists, all client requests are serviced by that instance. If an instance does not exist, the server creates an instance, and all subsequent client requests will be serviced by that instance. Singleton objects have a lease-based lifetime associated with them, and they may be destroyed if their lease expires and they are not renewed by a sponsor.

When a client creates an instance of a server-activated object, the .NET remoting infrastructure returns a proxy to the client, but it will not actually create the object on the server. The server application domain will create the object when the client makes a method call on the object. This saves a network round trip, but it does mean that only default constructors are allowed for server-activated types because the server cannot specify a particular constructor when it creates the object. If you try to instantiate an object that is configured to use server activation, and you use a nondefault constructor, you will get a system.runtime.remoting error with the following message:

 Cannot run a non-default constructor when connecting to well-known objects 
CLIENT ACTIVATION

Client-activated objects are objects with lifetimes that are controlled by their client. The client explicitly creates a new instance of an object using the new operator or the CreateInstance method on the System.Activator class. With client activation, a client proxy is created, and a network round trip to the server occurs to create the object immediately at activation time. The object will remain extant until its lease expires. Client-activated objects support nondefault constructors. Client activation more closely mimics the functionality of DCOM because it allows you to create stateful objects. The .NET Framework uses lease-based life cycle management for client-activated objects.

Lease-Based Life Cycle Management

In a distributed environment, the client proxy and the server object reside on different machines and thus use different instances of the CLR. Therefore, their life cycles must be managed separately. If no object pointers reference the proxy object on the client, it may be garbage-collected, but that doesn't automatically mean that the server object will be garbage-collected also. Ideally, when the proxy is garbage-collected on the client, it should send a message to the runtime on the server machine that it may release its reference to the remote object, which should eventually cause the remote object to be garbage-collected . Unfortunately, this approach is not sufficient. If you used only this scheme for life cycle management of remote objects and the client application crashed before it sent its release notification to the remote object, the remote object could continue to live on the server indefinitely.

The .NET Framework uses leased-based life cycle management to solve this problem. The .NET remoting infrastructure associates a lease with each remote object. A lease is an object that implements the System.Run-time.Remoting.Lifetime.ILease interface. The ILease interface has the members in Table 11-1.

Table 11-1. The members of the ILease interface

Property

Description

Default

InitialLeaseTime

The amount of time initially assigned to the lease.

5 minutes (zero=indefinite)

CurrentLeaseTime

The amount of time remaining on the lease.

N/A

CurrentState

The current state of the lease. Possible values are Active, Expired , Initial, Null, and Renewing.

N/A

RenewOnCallTime

The amount of time to add to the current lease time after each method call on the remote object.

2 minutes

SponsorshipTimeout

The amount of time to wait for a sponsor to renew the lease.

2 minutes

Register

A method that you can call to register a sponsor for the lease.

N/A

Unregister

A method that you can call to unregister one of a lease's sponsors.

N/A

Renew

A method that you can call to renew a lease.

N/A

Another important lease- related property is the LeaseManagerPollTime, which is the amount of time that the lease manager will sleep after checking for expired leases.

Each lease starts with an initial time as specified in the InitialLeaseTime property. Periodically, a piece of software in the .NET remoting infrastructure called a lease manager will check to see if there are any expired leases. The lease manager will use the LeaseManagerPollTime property to determine how often to check for expired leases. If a lease has expired, the lease manager will either cancel the lease by removing its reference to the lease, or it will renew the lease by calling one of the lease's sponsors. A lease can also be renewed each time a method is called on the object that the lease is associated with, or a client can renew a lease explicitly. If the lease manager cancels a lease, it will also remove all of its reference to the object associated with the lease, which will make the object eligible for garbage collection.

You can configure lease-related properties in two ways: (1) You can override the MarshalByRefObject.InitializeLifetimeService method in your marshal-by-reference object, or (2) you can specify lease-related properties in the <lifetime> element in the application or machine configuration file. You will see examples of how to do both in the examples that I do in this chapter.


Team-Fly    
Top
 


. Net and COM Interoperability Handbook
The .NET and COM Interoperability Handbook (Integrated .Net)
ISBN: 013046130X
EAN: 2147483647
Year: 2002
Pages: 119
Authors: Alan Gordon

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