Programmatic Registration

In Chapter 2, you learned how to register .NET Remoting channels for a component host and a client that uses configuration files. As with most tasks in .NET, anything you can do, you can do in code.

Consider the following configuration file, which you might remember from Chapter 2. It defines a single registered SingleCall object type and a TCP/IP listening channel on port 8080.

 <configuration>    <system.runtime.remoting>       <application name="SimpleServer">          <service>             <wellknown mode="SingleCall"                        type="RemoteObjects.RemoteObject, RemoteObjects"                        objectUri="RemoteObject" />          </service>          <channels>             <channel ref="tcp server" port="8080" />          </channels>       </application>    </system.runtime.remoting> </configuration> 

Using types in the System.Runtime.Remoting and System.Runtime.Remoting.Channels namespaces, you can perform the same work at startup, as shown in Listing 11-16.

Listing 11-16 Server-side dynamic registration
 Imports System.Runtime.Remoting Imports System.Runtime.Remoting.Channels. Imports System.Runtime.Remoting.Channels.Tcp Public Class HostForm     Inherits System.Windows.Form     ' (Windows designer code omitted.)     Private Sub HostForm_Load(ByVal sender As System.Object, _      ByVal e As System.EventArgs) Handles MyBase.Load     RemotingConfiguration.ApplicationName = "SimpleServer"     ' Define the channel.     Dim Channel As New TcpServerChannel(8080)     ' Register the channel. 
     ChannelServices.RegisterChannel(Channel)     ' Register the remote object type.     RemotingConfiguration.RegisterWellKnownServiceType( _       GetType(RemoteObjects.RemoteObject), _       "RemoteObjects.RemoteObject", _       WellKnownObjectMode.SingleCall)     End Sub End Class 

This example uses the TcpServerChannel class, although you also can use TcpChannel for a bidirectional channel or TcpClient for a client channel. Similarly, the System.Runtime.Remoting.Channels.Http namespace includes an HttpServerChannel, an HttpClientChannel, and an HttpChannel.

The only difference between this code and the Chapter 2 example (other than the fact that you no longer need a configuration file) is that the component host requires a reference to the remote object assembly. Otherwise, the call to the RemotingConfiguration.RegisterWellKnownServiceType method generates a compile-time error. Specifically, .NET won't be able to retrieve a Type object that represents the class. The offending code is shown here:

 RemotingConfiguration.RegisterWellKnownServiceType( _   GetType(RemoteObjects.RemoteObject), _   "RemoteObjects.RemoteObject", _   WellKnownObjectMode.SingleCall) 

The RegisterWellKnownServiceType method enables you to register SingleCall and singleton object types. You can also use the RegisterActivatedServiceType for a client-activated object.

Just as you can register channels, you also can unregister them. This can come in handy because attempting to reregister a channel that's already registered will fail.

Listing 11-17 uses the ChannelServices.RegisteredChannels to retrieve all the currently registered channels and systematically unregisters each one.

Listing 11-17 Unregistering all channels
 Dim Channel As IChannel For Each Channel In ChannelServices.RegisteredChannels     ChannelServices.UnregisterChannel(Channel) Next 

At this point, you might be wondering why you would want to perform programmatic registration. One of the most obvious problems is that programs that use this technique need to be recompiled if you want to use a different server, port, or communication method. However, programmatic registration also makes possible some new registration techniques.

Consider the case in which you want to register a component host that listens on several different channels. In a configuration-file-based approach, this is awkward because of naming collisions. With programmatic registration, it's easy. All you do is specify a unique name when you create the channel or use an empty string. The empty string tells .NET to ignore names but prevent naming conflicts.

 ' Listen for object requests over TCP/IP on several different ports. Dim Channel1 As New TcpChannel("", 8000) Dim Channel2 As New TcpChannel("", 8040) Dim Channel3 As New TcpChannel("", 8100) 

Another trick is to create a generic component host that automatically exposes any remotable types in a referenced assembly. Listing 11-18 demonstrates this technique.

Listing 11-18 Exposing all the remotable types in an assembly
 Dim RemoteObjects As System.Reflection.Assembly ' Find the System.Reflection.Assembly object representing the assembly ' where the RemoteObject type is defined. RemoteObjects = GetType(RemoteObject).Assembly ' Process all the types in this namespace. Dim Obj As Type For Each Obj in RemoteObjects.GetTypes()     ' Check if the type is remotable.     If Obj.IsSubclassOf(GetType(MarshalByRefObject)) Then         ' Register each type using the fully qualified type name         ' (like RemoteObjects.RemoteObject).         RemotingConfiguration.RegisterWellKnownServiceType( _           Obj, Obj.FullName, WellKnownObjectMode.SingleCall)     End If Next 

With this technique, you might still use a configuration file to specify channel information, but you use runtime logic to determine what objects to provide through .NET Remoting.

Note

You might want to enhance this example by developing a custom attribute. The component host can then examine the attributes applied to each type in the assembly and instantiate them only if it finds your custom attribute. Alternatively, the attribute might indicate which URI or activation type it should use when registering the type.




Microsoft. NET Distributed Applications(c) Integrating XML Web Services and. NET Remoting
MicrosoftВ® .NET Distributed Applications: Integrating XML Web Services and .NET Remoting (Pro-Developer)
ISBN: 0735619336
EAN: 2147483647
Year: 2005
Pages: 174

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