Activating the remote object

The last task to perform to host the remote object is to register the assembly with the remoting framework. In your host application, before you can activate the assembly that contains your methods, you first need to add a reference to the assembly. Right-click the References object in the Solution Explorer, which brings up the Add Reference dialog box. In the application you are writing here, you need to browse to the C:\cSharpRemoting\HostObject directory and add the HostObject.dll assembly to your application. After you add this, you can add the HostObject namespace to your class file using the using statement, as the following snippet shows:

using System;

using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels.Tcp; using HostObject;

Now that you have added a reference to your remoting assembly created earlier, you can add the code that registers the object with the remoting framework. You can do this in one of two ways:

• Use the RegisterWellKnownServiceType() method of the Remoting- Configuration class to pass the type of the object that you are creating, the URI of the object, and the activation mode of the object.

• Use the Configure() method of the RemotingConfiguration class to pass a configuration file with the object activation details.

Each activation method works the same way, but storing your activation details in a configuration file gives you more flexibility if any of the activation details change, such as the port number of the channel you are using. You will consider both types of activation, but first examine the available methods and properties of the RemotingConfiguration class described in Table 36-5 and Table 36-6, respectively. Besides the activation methods described previously, you can use many helpful methods and properties in this class to discover information at runtime about your running objects.

Table 36-5: RemotingConfiguration class Methods

Method

Description

Configure

Reads the configuration file and configures the remoting infrastructure.

GetRegisteredActivatedClientTypes

Retrieves an array of object types registered on the client as types that will be activated remotely.

GetRegisteredActivatedServiceTypes

Retrieves an array of object types registered on the service end as types that can be activated on request from a client.

GetRegisteredWellKnownClientTypes

Retrieves an array of object types registered on the client end as well-known types.

GetRegisteredWellKnownServiceTypes

Retrieves an array of object types registered on the service end as well-known types.

GetType (inherited from Object)

Gets the type of the current instance.

IsActivationAllowed

Returns a Boolean value indicating whether the specified type is allowed to be client activated.

IsRemotelyActivatedClientType

Overloaded. Checks whether the specified object type is registered as a remotely activated client type.

IsWellKnownClientType

Overloaded. Checks whether the specified object

Table 36-5: RemotingConfiguration class Methods

Method

Description

type is registered as a well-known client type.

RegisterActivatedClientType

Overloaded. Registers an object type on the client end as a type that can be activated on the server.

RegisterActivatedServiceType

Overloaded. Registers an object type on the service end as one that can be activated on request from a client.

RegisterWellKnownClientType

Overloaded. Registers an object type on the client end as a well-known type (single call or singleton).

RegisterWellKnownServiceType

Overloaded. Registers an object Type on the service end as a well-known type (single call or singleton).

Table 36-6: RemotingConfiguration Class Properties

Property

Description

ApplicationId

Gets the ID of the currently executing application

ApplicationName

Gets or sets the name of a remoting application

ProcessId

Gets the ID of the currently executing process

Registering objects with RegisterWellKnownServiceType

To register an object with the RegisterWellKnownServiceType() method of the RemotingConfiguration class, you simply pass the name of the class, which is HostObject.Class1; the URI of the remote object, which is ReturnName; and the type of mode in which the object will be created, which in this case is SingleCall. You look at the WellKnownObjectMode enumeration later in this section. Listing 36-3 completes the host application using the RegisterWellKnownServiceType method.

Listing 36-3: Using RegisterWellKnownServiceType using System;

using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels.Tcp; using HostObject;

namespace Host {

/// Summary description for Classl. /// </summary>

class Classl

/// The main entry point for the application. /// </summary>

[STAThread]

static void Main(string[] args) {

TcpChannel chanl = new TcpChannel(8 085);

ChannelServices.RegisterChannel(chanl);

RemotingConfiguration.RegisterWellKnownServiceType( typeof(HostObject.Classl), "ReturnName", WellKnownObjectMode.SingleCall);

Console.WriteLine("Press any key to exit"); Console.ReadLine();

Because the host application is a console application, you add the Console. ReadLine statement at the end so that the console window stays open while clients are using the remote object. The lifetime of the channel is the length of time that window happens to be open. After you close the console window, the channel is destroyed and the lease on that particular channel is expired in the remoting framework.

The WellKnownObjectMode enumeration contains two members that define how objects are created. If the WellKnownObjectMode is SingleCall, then each request from a client is serviced by a new object instance. This would be represented by the following pseudo-code:

Create Object X Call Method of Object X Return data back to caller Destroy Object X Garbage Collect

If the WellKnownObjectMode is Singleton, then each request from a client is serviced by the same object instance. This can be described in the following pseudo-code:

Create Object X

Call Method of Object X

Return data back to caller

Call Method of Object X

Return data back to caller

... continue until channel destroyed

This loop continues until the channel with which this object is registered in the remoting framework is destroyed.

Depending on the type of application you are writing, you determine which activation mode to use by considering the following factors:

• Overhead: If creating the remote object consumes resources and takes time, then using the SingleCall mode may not be the most efficient way to create your object, as the object is destroyed after each client is done using it.

• State Information: If you are storing state data in your remote object, such as properties, you use Singleton objects, which are capable of maintaining state data.

Registering objects with the Configure method

If you need a more flexible way of maintaining the configuration data that the remoting framework needs to register your object, you can use the Configure() method of the RemotingConfiguration class. The configuration information that is stored in the file is the same information that you can use in the RegisterWellKnown- ServiceType() method. The benefit of using a configuration file is that if any of the settings for the object change, you can alter the configuration file, and not change any of your code. The schema for the configuration is shown in Listing 36-4, with the explanation of each element in Table 36-7.

Listing 36-4: Remoting Configuration File

<configuration>

<system.runtime.remoting> <application> <lifetime>

<channels> (Instance) <channel> (Instance)

<serverProviders> (Instance) <provider> (Instance) <formatter> (Instance) <clientProviders> (Instance) <provider> (Instance) <formatter> (Instance)

<client>

<wellknown> (Client Instance) <activated> (Client Instance) <service>

<wellknown> (Service Instance) <activated> (Service Instance) <soapInterop>

<interopXmlType> <interopXmlElement> <preLoad> <channels> (Template) <channel> (Template)

<serverProviders> (Instance) <provider> (Instance) <formatter> (Instance) <clientProviders> (Instance) <provider> (Instance) <formatter> (Instance) <channelSinkProviders>

<serverProviders> (Template) <provider> (Template) <formatter> (Template) <clientProviders> (Template) <provider> (Template) <formatter> (Template)

Although there are many options in the configuration file, you only need to use what your application requires. For example, the snippet of code in Listing 36-5 represents a configuration file for an HTTP-activated object that is a SingleCall mode object.

Listing 36-5: Configuration File Example

<configuration>

<system.runtime.remoting> <application>

<client url="http://localhost/HostObject"> <wellknown type="HostObject.Class1, ReturnName"

url="http://localhost/HostObject/Class1.soap" /> </client>

<channels>

<channel ref="http" /> </channels>

</application> </system.runtime.remoting> </configuration>

After you create the configuration file, creating the host object is dramatically simpler than it is when registering an object with the RegisterWellKnown- ServiceType() method of the RemotingConfiguration class. The code in Listing 36-6 demonstrates how to register the object using the Configure() method.

Listing 36-6: Using a Remoting Configuration File in the Host Class namespace Host

/// Summary description for Class1. /// </summary>

class Class1 {

/// The main entry point for the application.

[STAThread]

static void Main(string[] args) {

RemotingConfiguration.Configure("Host.Exe.Config");

Console.WriteLine("Press any key to exit"); Console.ReadLine();

As you can see, your code is reduced from about 15 lines to 1 line.

Note The name of the configuration file should be the name of the executable, including the exe extension, with an additional config extension added. In the case of the host application, the configuration file would be named host.exe.config, and the file would be located in the Bin directory where the executable file for the host application resides.

Table 36-7 lists all of the available elements and their uses for the remoting configuration file schema.

Table 36-7: Schema for Remoting Settings Configuration File

Element

Description

<system.runtime.remoting>

Contains information about remote objects and channels

<application>

Contains information about remote objects that the application consumes and exposes

<lifetime>

Contains information about the lifetime of all client-activated objects serviced by this application

<channels> (Instance)

Contains channels that the application uses to communicate with remote objects

<channel> (Instance)

Configures the channel that the application uses to communicate with remote objects

<serverProviders> (Instance)

Contains providers for channel sinks that are to become part of the default server-side channel sink call chain for this channel template when the template is referenced elsewhere in the configuration file

<provider> (Instance)

Contains the channel sink provider for a channel sink that is to be inserted into the channel sink chain

<formatter> (Instance)

Contains the channel sink provider for a formatter sink that is to be inserted into the channel sink chain

<clientProviders> (Instance)

Contains providers for channel sinks that are to become part of the default client-side channel sink call chain for this channel template when the template is referenced elsewhere in the configuration file

<client>

Contains objects that the application consumes

<wellknown> (Client Instance)

Contains information about server-activated (well-known) objects the application wants to consume

<activated> (Client Instance)

Contains information about client-activated objects the application wants to consume

<service>

Contains objects that the application exposes to other application domains or contexts

<wellknown> (Service Instance)

Contains information about server-activated (well-known) objects the application wants to publish

Table 36-7: Schema for Remoting Settings Configuration File

Element

Description

<activated> (Service Instance)

Contains information about client-activated objects the application wants to publish

<soapInterop>

Contains type mappings used with SOAP

<interopXmlType>

Creates a bidirectional map between a common language runtime type and an XML type and XML namespace

<interopXmlElement>

Creates a bidirectional map between a common language runtime type and an XML element and XML namespace

<preLoad>

Specifies the type to load the mappings from classes that extend SoapAttribute

<channels> (Template)

Contains channel templates that the application uses to communicate with remote objects

<channel> (Template)

Contains the channel template that specifies how to communicate with or listen to requests for remote objects

<channel SinkProviders>

Contains templates for client and server channel sink providers. Any channel sink providers specified underneath this element can be referenced anywhere a channel sink provider might be registered

<serverProviders> (Template)

Contains channel sink templates that can be inserted into a server channel call chain

<provider> (Template)

Contains the channel sink provider template for a channel sink that is to be inserted into the server or client channel sink chain

<formatter> (Template)

Contains the channel sink provider for a formatter sink that is to be inserted into the client or server channel sink chain

<clientProviders> (Template)

Contains channel sink templates that can be inserted into a client channel call chain

<debug>

Specifies whether types should be loaded in the configuration file when the application starts

Until this point, this chapter has explained the intricacies of creating the host application that registers the remote object with the remoting framework. Now you need to write the client application that makes the requests to the remote object, which is the subject of the next section.

0 0

Post a comment