Google
WWW Yariv Hammer's Code Site

Wednesday, October 26, 2005

How To Get the Singleton Instance of a Remote Object in the Server and in the Client

Introduction
If we are using Singleton classes in the Remoting session, that means that all the clients will access the same copy of the object that lives in the Server process.
I will show a good way of getting the instance of the singleton object, and a way of getting this instance in the server.

Using Singleton Objects
Generally speaking, the Singleton design pattern is not supported for classes. You wll need to implement it yourself (private constructor, static Instance property, you know the deal). But for Remoting objects (MarshalByRefObjects) there is no need for such explicit implementation. When you register the object for remoting in the server:
--------------------------------

RemotingConfiguration. RegisterWellKnownServiceType( typeof(RemoteObject), "MyServer", WellKnownObjectMode.Singleton );

--------------------------------
And the object will be a Singleton without it showing in the code.

Getting the Remote Singleton In the Client
The following class should be in the Client application (or referenced by it). It is a generic factory to get remote objects (not necessarily Singletons):
------------------------------------

public class RemotingHelper
{
   internal static bool _isInit = false;
   private static IDictionary _wellKnownTypes;
   public static object GetObject(Type type)
   {
      if (!_isInit)
         InitTypeCache();
      WellKnownClientTypeEntry entr = (WellKnownClientTypeEntry) _wellKnownTypes[type];
      if (entr==null)
         throw new RemotingException("Type not found");
      return Activator.GetObject(entr.ObjectType,entr.ObjectUrl);
   }

   private static void InitTypeCache()
   {
      _wellKnownTypes = new Hashtable();
      foreach(WellKnownClientTypeEntry entr in RemotingConfiguration. GetRegisteredWellKnownClientTypes())
         _wellKnownTypes.Add(entr.ObjectType,entr);
      _isInit = true;
   }
}

-----------------------------------
use RemotingConfiguration.GetObject(typeof(whatever)) to get the remote object.
This class is very efficient because it uses Hashtable to store the objects. It will throw an exception when the type is not registered for remoting in the client or server. It is generic!!! You can use it in every client you write with no regards to the object types.

Getting the Remote Singleton In the Server
If you do this in the server:
RemoteObject obj = new RemoteObject();
You will get a new instance of the RemoteObject. You will not get the actual copy that the clients are using. This is important to know!!!

So I put a class in the Server application (or referenced by it) which has a Hashtable similar to the one I showed before:
-------------------------------------------------

public class RemoteSingletonObjectsList
{
   private static RemoteSingletonObjectsList _instance = new RemoteSingletonObjectsList();
   public static RemoteSingletonObjectsList Instance
   {
      get { return _instance; }
   }
   private RemoteSingletonObjectsList() { }
   private Hashtable _objects = new Hashtable();
   public void RegisterRemoteSingletonObject(object obj)
   {
      _objects[obj.GetType()] = obj;
   }
   public object GetRemoteSingletonObject(Type type)
   {
      return _objects[type];
   }
}

------------------------------------------------
The following method should be called from the Main of the server before running the Form:
------------------------------------------------

private static void InitRemoting()
{
   foreach (WellKnownServiceTypeEntry entry in RemotingConfiguration. GetRegisteredWellKnownServiceTypes())
   {
      MarshalByRefObject pxy = (MarshalByRefObject) Activator.GetObject(entry.ObjectType, "tcp://localhost:port/MyServer/" + entry.ObjectUri);
      pxy.CreateObjRef(entry.ObjectType);
      RemoteSingletonObjectsList.Instance. RegisterRemoteSingletonObject(pxy);
   }
}

------------------------------------------------
The Activator.GetObject and MarshalByRefObject.CreateObjRef methods do the work of getting the Remote objects.

When you need the object in the server you call RemoteSingletonObjectsList.GetRemoteSingletonObject(typeof(whatever)).

0 Comments:

Post a Comment

<< Home

Feel free to use everything here. Add links to my site if you wish.

Do not copy anything to other sites without adding link to here.

All the contents of the site belong to Yariv Hammer.