Publishing and Activation

When publishing an object service to the remoting system, the programmer needs to be aware of the different activation and life cycle models that are available. There are two types of activation—client activation and server activation—both of which are handled by the System.Runtime.Remoting.RemotingConfiguration class.

  • When a server publishes a service, the activation type defines how and when the object will be created, and how the life cycle of the object will be controlled.

  • When a client registers for an activated service, the runtime is provided with information about how to create new proxies to represent the remote type. Calls to create instances of the registered type using the new keyword will be translated into the appropriate remoting operations.

Client Activation

With client activation, a new instance of the published object is created on the server when the client instantiates a local reference. Each new instance on a client will lead to the creation of a new instance of the published object on the server, resulting in a one-to-one mapping between client proxies and instances of the server object.

The client controls the life cycle of the server object. The server won’t free the object until the client has finished with it or the client has exited.

We would register the example service in the following way to support client activation:

RemotingConfiguration.RegisterActivatedServiceType(typeof(Server));

Clients register a mapping for the type as follows:

RemotingConfiguration.RegisterActivatedClientType(
    typeof(Server), "http://localhost:20172");

After the client has registered for the activated type, calls to new Server( ) will cause a new instance of the Server class to be created at the server and a proxy representing this instance to be created at the client. Once a type has been registered for remoting, local instances (those that will not be remoted) can no longer be created.

Key points worth highlighting include the following:

  • The URL used by clients to register for a client-activated service doesn’t contain the service name.

  • Because the remote object is created in response to the new keyword, constructors with arguments can be used to instantiate remote objects.

Server Activation

The lifetime of a server-activated object is controlled directly by the server. When the client creates a new instance of the remote type, a proxy is created local to the client, but the instantiation of the remote type at the server is deferred until the client invokes a remote type member via the proxy. Key points worth highlighting include the following:

  • No network call is made when the remote type is instantiated.

  • Only default constructors can be used because the construction of the remote object is deferred until the client has invoked a method and there are no means to pass constructor arguments.

There are two variations of server activation, which are defined in the System.Runtime.Remoting.WellKnownObjectMode enumeration: Singleton and SingleCall.

Clients register for both kinds of server-activated type in the same way, as shown in the example at the start of this chapter:

RemotingConfiguration.RegisterWellKnownClientType(
    typeof(Server), "http://localhost:20172/CountServer");

The URL that is passed as an argument is a composite of a channel URL and the name of the service, specified in the server registration. Because the server controls the lifetime of the remote object, the client doesn’t need to be aware of the server-activation model used.

Singleton

The first variant of server activation is Singleton, wherein the remoting system directs all remote method requests to a single instance of the activated class. The runtime guarantees zero or one instance of the published class will be in existence and that a single instance will be created and shared as required to service client requests. By default, a type instance used as a Singleton will be released if no clients make a request for 5 minutes. When this happens, there will be no instances of the published class until the next client invokes a method via a proxy, at which time a new instance will be created.

Overriding the MarshalByRefObject.InitializeLifetimeService method to return null creates a Singleton that never expires. See the section on lifetime leases for more information.

The original example (in Creating the Server) demonstrated a Singleton type; the key statement from the Start class follows:

RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(Server), "CountServer", WellKnownObjectMode.Singleton);

The first argument is the type that should be created in response to client invocations, the second argument is the name of the service to be published, and the final argument is the Singleton flag.

SingleCall

The SingleCall server-activation variation creates a new instance of the published type for each member invocation from a remote client. The instance is released for garbage collection after the member has completed execution.

Servers register a SingleCall type as follows:

RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(Server), "CountServer", WellKnownObjectMode.SingleCall);

Publishing an Existing Instance

Because both Singleton and SingleCall activation types create instances using the default constructor, the programmer cannot configure instances of the class by passing in arguments during construction. However, it is possible to publish an already created and configured instance of the class as a Singleton using the following call:

RemotingServices.Marshal(myObjectInstance,"myServiceName");

Instances published in this way have an idle time of 5 minutes. Override the MarshalByRefObject.InitializeLifetimeService to return null if the instance should be available indefinitely. If this method isn’t overridden, client attempts to perform operations on the remoting service will throw exceptions because the remoting system is unable to create new instances after the original has expired.

Individual instances can be made unavailable to remote clients by calling the RemotingServices.Disconnect method. The argument for this method is the instance that was published, so it’s important to keep a reference to published instances if the instance needs to be withdrawn at a later time. When an instance is withdrawn from service, client attempts to perform operations will throw an exception.

Using Configuration Files

The foregoing examples demonstrate how to publish and activate remote objects programmatically. The remoting system also allows remoting to be controlled via XML configuration files. For general information about using .NET configuration files, see Appendix C.

The configuration file requires that channels and published types be declared separately; this reflects the fact that all channels within an application can be used for all published types. All remoting information is contained in the configuration/system.runtime.remoting/application section of the configuration file.

Configuration information can be stored in the same file as other application settings but must be loaded explicitly using the Configure method in the System.Runtime.Remoting.RemotingConfiguration class; other configuration settings are loaded automatically by the common language runtime, but this is not the case for remoting settings.

Defining Channels

Channels are defined using the <channels> element, as shown in the following example:

<configuration>
    <system.runtime.remoting>
        <application>
          <channels>
                <channel ref="http" port="0"/>
          </channels>
        </application>
    </system.runtime.remoting>
</configuration>

Using this file, we can update the CountClient constructor to load the configuration information in order to define the client HTTP channel, as shown here:

CountClient() {
    // load the remoting configuration file
    RemotingConfiguration.Configure("RemotingConfig.xml");

    // local member to initialize the remoting system
    InitRemoteServer();

    DoRemoteSummation(new CountServer());
}

The statement marked in boldface loads the configuration information, assuming that the details have been saved to a file named RemotingConfig.xml. The contents of the configuration file are equivalent to the following programmatic statements:

HttpChannel x_channel = new HttpChannel();
ChannelServices.RegisterChannel(x_channel);

Server Configuration

Types are published for remoting using the <service> element. The following example demonstrates how to publish a server-activated type:

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

            <service>
                <wellknown mode="Singleton"
                    type="CountServer.Server, CountServer"
                    objectUri="CountServer" />
            </service>

            <channels>
                <channel ref="http" port="20172"/>
            </channels>
        </application>
    </system.runtime.remoting>
</configuration>

The <well-known> element defines the activation mode (Singleton or SingleCall), the type, and the URI that will be used to access the service. The type attribute is a combination of the fully qualified type name and the name of the assembly that the type is contained in, separated by a comma. The preceding configuration example is equivalent to the following C# statements:

HttpChannel x_channel = new HttpChannel(20172);
ChannelServices.RegisterChannel(x_channel);

RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(CountServer.Server), "CountServer",
    WellKnownObjectMode.Singleton);

Client-activated types are defined as in the following example:

<configuration>
    <system.runtime.remoting>
        <application>
            <service>
                <activated type="CountServer.Server, CountServer"/>
            </service>

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

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

The previous configuration file is equivalent to the following C# statements:

HttpChannel x_channel = new HttpChannel(20172);
ChannelServices.RegisterChannel(x_channel);

RemotingConfiguration.RegisterActivatedServiceType(
    typeof(CountServer.Server));

Client Configuration

Client configuration is similar to the foregoing examples. The following configuration file demonstrates registering settings for a client-activated type:

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

            <client url="http://localhost:20172">
                <activated type="CountServer.Server, CountServer"/>
            </client>

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

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

The URL attribute of the client element is used to indicate the server details. This configuration file is equivalent to the following C# statements:

HttpChannel x_channel = new HttpChannel();
ChannelServices.RegisterChannel(x_channel);
RemotingConfiguration.RegisterActivatedClientType(
    typeof(CountServer.Server),
    "http://localhost:20172");

The following configuration file demonstrates settings for a server-activated type:

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

            <client>
                <wellknown
                    type="CountServer.Server, CountServer"
                    url="http://localhost:20172/CountServer"/>
            </client>

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

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

This configuration file is equivalent to the following C# statements:

HttpChannel x_channel = new HttpChannel();
ChannelServices.RegisterChannel(x_channel);
RemotingConfiguration.RegisterWellKnownClientType(
    typeof(Server),
    "http://localhost:20172/CountServer");

Publishing Limitations and Scope

For the most part, dealing with remote objects is just like dealing with local objects, but in some situations this is not the case.

Methods in the Object Class

Calls to the following methods will be sent to the remote object only if the published type overrides the default implementation in the System.Object class:

  • GetHashCode

  • Equals

  • ToString

  • MemberwiseClone

Calls to the static version of Object.Equals will never be sent to the remote object.

Private Methods and Delegates

Private methods cannot be used remotely. With a local object, it’s possible to use a delegate to pass a reference to a private method to another class. The remoting system doesn’t allow private methods to be used in this manner. Where delegates are used, the object passed to the delegate must be a valid remote type, either annotated with the Serializable attribute or derived from System.MarshalByRefObject.

Static Fields and Methods

Static members are never remoted. When a static method or field is called, the local class definition is used to satisfy the request. This can be problematic, especially in multithreaded environments, when instance members rely on static fields that are changed as a result of static method calls.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset