Messages
You ll see a lot of messages throughout the rest of this book because they re the fundamental unit of data transfer in .NET Remoting applications. Because .NET Remoting objects such as proxies and message sinks use messages extensively, let s discuss messages in more detail before we begin customizing those other objects.
Recall from Chapter 2, Understanding the .NET Remoting Architecture, that all .NET Remoting messages derive from IMessage. IMessage merely defines a single IDictionary property named Properties. IDictionary defines an interface for collections of key-and-value pairs. Because both the keys and values of IDictionary-based collections contain elements of type object, you can put any .NET type into these collections. But the objects you use must be serializable in order to be transported across a remoting boundary. We ll look at serialization in depth in Chapter 8, Serialization Formatters.
Construction Call Messages
When you make a method call (including a constructor call) on a remote object, the .NET Remoting infrastructure constructs a message describing the method call. For example, consider the following client code:
Object obj = new MyRemoteObject();
The instantiation of the MyRemoteObject results in the instantiation of a .NET Remoting message with the IDictionary entries shown in Table 5-1.
Dictionary Key | Dictionary Value Data Type | Dictionary Value |
__Uri | String | null |
__MethodName | String | .ctor |
__TypeName | System.String | MyNameSpace.MyRemoteObject, MyAssembly, Version=1.0.882.27668, CultureNeutral, PublicKeyToken=null |
__MethodSignature | Type[] | null |
__Args | Object[] | null |
__CallContext | LogicalCallContext | null |
__ActivationType | Type | null |
__CallSiteActivationAttributes | Object[] | null |
__ActivationType | Type | null |
The value of the __MethodName key identifies the method as .ctor, which corresponds to the MyRemoteObject constructor method. Because MyRemote Object s constructor has no arguments, the __MethodSignature and __Args values are null. Because call context can be set in the client s calling code, the dictionary contains a key named __CallContext. We ll discuss call context and how to use it in the next section of this chapter. Finally, the message has dictionary keys for custom activation properties, which the .NET Remoting infrastructure uses during activation.
Method Call Messages
Consider the following method on the remote object:
Obj.MyMethod("A string", 14);
This method call results in the generation of a message with the IDictionary entries shown in Table 5-2.
Dictionary Key | Dictionary Value Data Type | Dictionary Value |
__Uri | String | null |
__MethodName | String | MyMethod |
__TypeName | System.String | MyNameSpace.MyRemoteObject, MyAssembly, Version=1.0.882.27668, CultureNeutral, Public KeyToken=null |
__MethodSignature | Type[] | [0] = System.String [1] = System.Int32 |
__Args | Object[] | [0] = a string [1] = 14 |
__CallContext | LogicalCallContext | null |
Note that the __MethodName, __MethodSignature, and __Args keys are populated to reflect the remote object s method. Because the object has already been activated, the activation keys aren t present.
Message Types
All .NET Remoting messages implement the IMessage interface so that they at least have a single IDictionary property. The .NET Remoting infrastructure derives many interfaces from IMessage that generally serve two purposes. First, each of these interfaces provides various properties and/or methods to make accessing the IMessage internal dictionary more convenient. Second, each interface s specific type serves as a marker so that you know how to handle the message. For example, you might want to differentiate between a message for constructing a client-activated object and a message generated from a regular method call. Although either of these messages could be conveyed via a simple IMessage class, by having different types the interfaces can inform you of the intent of a message. Table 5-3 summarizes the common message interfaces and classes that you might encounter.
Message Type | Member Name (Partial Listing) | Description |
IMessage | Implemented by all .NET Remoting messages. | |
IMethodMessage | Implemented by all messages that describe stack-based methods. Specifies properties common to all methods. | |
Args | Array of method arguments passed. | |
MethodName | Name of the method that originated the message. | |
Uri | Uniform Resource Identifier (URI) of the object that this message is destined for. | |
TypeName | Full type name of the object that this message is destined for. | |
IMethodReturnMessage | Implemented by all messages returning to the client. | |
Exception | Exception thrown by the remote object, if any. | |
OutArgs | Array of [out] arguments. | |
ReturnValue | Object containing the return value of the remote method, if any. | |
IMethodCallMessage | Implemented by all messages originating from method calls. Specifies properties common to all method calls. | |
InArgs | Array of [in] arguments. | |
IConstructionCallMessage | Message implementing this interface is sent to a client-activated object when you call new or Activator.CreateInstance. Server-activated objects receive this message when you make the first message call. As its name implies, this is the first message sent to an object, and it specifies properties common to remote object construction. | |
ActivationType | Gets the type of the remote object to activate. | |
Activator | Gets or sets the activator used to activate the remote object. | |
ContextProperties | Gets the list of context properties that define the object s creation context. | |
IConstructionReturnMessage | Message implementing this interface is sent back to the client in response to an IConstructionCallMessage. | |
ReturnMessage | Concrete class that implements IMethod ReturnMessage. This class is documented so that you can conveniently construct your own return message if you want to intercept a method call to return a valid message without involving the remote object. |
Now that we ve discussed messages, we can start looking at the .NET Remoting objects that handle messages. We ll start at the client side, where remote object method calls originate and the .NET Remoting infrastructure creates the messages.