6. Administrative Type Registration
As with programmatic
type registration, the host configuration file can contain a list of the
objects it's willing to expose, either as client-activated objects or
as server-activated objects, and in what mode. The client configuration
file can contain a list of the types it wants to access remotely and
their URLs and URIs, if required. When the client or host references a
type, it must specify a fully qualified name (type name and its
namespace) as well as the type's assembly. Any misspellings or
namespaces incompatibilities will be discovered only at runtime.
6.1. Host type registration
The host uses the <service>
tag to contain a list of the types it exposes. Each type has an entry
indicating its activation mode and URI, if required. For example, here
is how the host registers the type MyClass from the RemoteServer namespace in the ServerAssembly assembly as a client-activated object:
<application>
<service>
<activated type="RemoteServer.MyClass,ServerAssembly"/>
</service>
</application>
The host can also expose the type MyClass as a server-activated object and specify the activation mode and the URI:
<application>
<service>
<activated type="RemoteServer.MyClass,ServerAssembly"/>
<wellknown type="RemoteServer.MyClass,ServerAssembly"
mode="SingleCall" objectUri="MyRemoteServer"/>
</service>
</application>
With administrative
configuration, the host is subjected to the same URI constraints as with
programmatic configuration. The host can also specify an application
name with the same semantics as assigning a name programmatically:
<application name="MyApp">
...
</application>
To register a generic type, provide the type parameter in double square brackets. For example, to register the class MyClass<T> with an integer, you should write:
<service>
<wellknown type="RemoteServer.MyClass[[System.Int32]],ServerAssembly"
mode="SingleCall" objectUri="MyRemoteServer"/>
</service>
The double square
brackets are required in case you need to specify multiple generic type
parameters, in which case each type parameter would be encased in a
separate pair of brackets, separated by a comma. For example, to
register the class MyClass<T,U> with an integer and a string, you would write:
<service>
<wellknown type="RemoteServer.MyClass[[System.Int32],[System.String]],
ServerAssembly" mode="SingleCall" objectUri="MyRemoteServer"/>
</service>
6.2. Client-side type registration
The client uses the <client>
tag to contain a list of the types it wants to consume remotely. It
must provide the objects' URLs and URIs, if required. The client can
register a given type only once, just as when registering
programmatically.
To register a type as a client-activated object, the client uses the <activated> tag, providing the type's name and assembly:
<application>
<client url="tcp://localhost:8005">
<activated type="RemoteServer.MyClass,ServerAssembly"/>
</client>
</application>
The object's URL is provided as an attribute of the <client> tag. To register a type as a server-activated object, the client uses the <wellknown> tag:
<application>
<client>
<wellknown type="RemoteServer.MyClass,ServerAssembly"
url="tcp://localhost:8005/MyRemoteServer"/>
</client>
</application>
Note that when you use the <wellknown> tag, the URL and URI are specified as attributes of the <wellknown> tag, rather than as attributes of the <client> tag.
If you need to register multiple remote types on the client's side, you need to use multiple <client> tags:
<application>
<client url="tcp://localhost:8005">
<activated type="RemoteServer.MyClass,ServerAssembly"/>
</client>
<client>
<wellknown type="RemoteServer.MyOtherClass,ServerAssembly"
url="tcp://localhost:8005/MyRemoteServer"/>
</client>
</application>
To register remote generic types on the client side, use the same syntax for describing the type parameters as the host.
The .NET Configuration
tool has what looks like visual administrative support for managing the
remoting part of an application configuration file. Unfortunately, that
support leaves much to be desired: the tool doesn't generate a blank
configuration file, and its ability to edit existing files with existing
remoting attributes is partial at best. |
|
7. Administrative Configuration Example
Example 3 demonstrates a host and client using a configuration file to provide remote access to the same object as in Example 1. The ServerAssembly class library is the same class library from Example 1, providing the class MyClass. The host configuration file exposes the MyClass
type both as a client-activated object and as a single-call object, and
it registers both TCP and HTTP as transport channels. The host calls RemotingConfigurationEx.Configure( ) in its Main( ) method and then displays a blank dialog. The client configuration file registers the type MyClass
as a client-activated object (the client can associate the type with
only a single activation mode). The client configuration file provides
the type's URL, using TCP as the transport channel. The client
application calls RemotingConfigurationEx.Configure( ) in its Main( )
method and then displays the client dialog. The client dialog has a
single button on it, allowing you to create new remote objects.
Example 3. Administrative remoting configuration using configuration files
///////////// RemoteServerHost.exe.config : the host configuration file ////////
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.runtime.remoting>
<application>
<service>
<activated type="RemoteServer.MyClass,ServerAssembly"/>
<wellknown type="RemoteServer.MyClass,ServerAssembly"
mode="SingleCall" objectUri="MyRemoteServer"/>
</service>
<channels>
<channel ref="tcp" port="8005"/>
<channel ref="http" port="8006"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>
///////////////////// RemoteServerHost EXE assembly ////////////////////////////
partial class ServerHostDialog : Form
{
public ServerHostDialog( )
{
InitializeComponent( );
}
void InitializeComponent( )
{...}
static void Main( )
{
RemotingConfigurationEx.Configure( );
Application.Run(new ServerHostDialog( ));
}
}
//////////////// Client.exe.config: the client configuration file //////////////
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.runtime.remoting>
<application>
<client url="tcp://localhost:8005">
<activated type="RemoteServer.MyClass,ServerAssembly"/>
</client>
</application>
</system.runtime.remoting>
</configuration>
/////////////////////////// Client EXE assembly ////////////////////////////////
using RemoteServer;
partial class ClientForm : Form
{
Button m_NewButton;
public ClientForm( )
{
InitializeComponent( );
}
void InitializeComponent( )
{...}
static void Main( )
{
RemotingConfigurationEx.Configure( );
Application.Run(new ClientForm( ));
}
void OnNew(object sender,EventArgs e)
{
MyClass obj;
obj = new MyClass( );
obj.Count( );
obj.Count( );
}
}
|