You usually implement a factory pattern as a class containing only static methods that return instances of objects. Think of a factory as being like a physical factory, you ask for something to be built, and the factory builds it and gives it to you.
In addition, the pattern serves to keep the entire object referenced between calls, so it behaves like an object and not a function library. If you had created the object by creating a remote reference directly to a CorporateAccountantTest instance you would have to do quite a bit more work to get a reference to the remote object. Listing 2
contains a complete listing of the implementation.
For your client program to be able to use the remote object, you will need to register it with ChannelServices. ChannelServices needs to know the name of the object, its location, and how to communicate with it.
Registering the implemented objects is fairly simple. First, create a TcpServerChannel using any unused port number, and then register that channel with ChannelServices.
Next, use RemotingConfiguration.RegisterWellKnownServiceType to use CorporateAccountantExamFactory as its type, and IExamFactory as the name used remote objects.
The final parameter on this method call declares that this is a SingleCall object meaning that it should behave like a function library instead of an object. A SingleCall object is used only once and all member variables of the object go back to their default values as soon as the method call is completed (see the sidebar Understanding Singletons
for more information about SingleCall objects). Here's a partial listing that shows the code to register a channel. For a complete listing of the RemotingServer object, see Listing 3
Client Side, An Exercise In Laziness
TcpServerChannel chl =
new TcpServerChannel(9988);//The Address
//Dropping the card in the box to register
"IExamFactory", //What the outside world calls it
WellKnownObjectMode.SingleCall);//How to contact
You can create a direct instance of the remote object, but doing so has some interesting implications. By directly creating the reference to the remote object you will have the "function library" effect. This is useful for high performance situations because the server does not have to keep every instance of the remote object in memory.
IAccountantTest directGrab =
The call to ChannelServices adds a new channel to the channel pool. You don't need to know anything about this other than that it creates a channel that is transparently available to your remote objects.
You use the Activator object to create instances of objects when you don't know at compile time exactly what objects the code requires. In Remoting, you use it because the actual code for the object exists somewhere else. In this case, the Activator object creates a reference to the object on the server. To create an instance, pass the Activator the Type object for the interface and the URL of the object you want to reference.
The output of the second call to WhatIsTwoPlusTwo()
is where the interesting behavior lies. The code returns the string "David"
even though the code in the preceding listing uses the SetName()
method to set the name to "Nadia!" The problem is that the SingleCall
object mode set on the server treats this object like a function library.
If the code had set the WellKnownObjectMode
on the server, it would have worked as expected; however then all
clients accessing the object on that server would see receive a return value of "Nadia," because only one instance of the object would exist on the server. Neither option provides the behavior you're looking for. Ideally, you want your remote objects to behave like local objects. That's where the factory comes in.