Working with singletons in .Net Remoting

Todd picture Todd · Apr 9, 2009 · Viewed 7.5k times · Source

I'm having a bit of a problem with a singleton class I'm exposing via remoting. In my server I have:

TcpChannel channel = new TcpChannel( Settings.Default.RemotingPort );
ChannelServices.RegisterChannel( channel, false );
RemotingConfiguration.RegisterWellKnownServiceType( 
    typeof( RemotableObject ), "RemotableObject", 
    WellKnownObjectMode.Singleton );

RemotableObject is a singleton object that inherits MarshalByRefObject.

My client connects to it via:

remoteObject = (RemotableObject)Activator.GetObject(
    typeof( RemotableObject ),
    string.Format( "tcp://{0}:{1}/RemotableObject", serverIP, serverPort ) );

Everything works great as far as the remoting goes, but when I access the singleton object in my server code like this:

int someValue = RemotableObject.Instance.SomeDynamicValue;

It accesses a different instance than the clients do. I have also verified that the private constructor in RemotableObject gets hit twice while debugging.

I can get the desired behavior if I get an instance to RemotableObject via remoting in my server code, but is there a way that I can access the same object as my clients from the server without the remoting overhead?

Answer

Charles Bretana picture Charles Bretana · Apr 9, 2009

If I understand what you're after, (you want the object to live on the server, but you want all client calls to get the same instance of the object on the server, and you also want calls in the server code to get that same instance? )

then, If your server is "ServerName", and it is listening on port nnnn, with Uri as "MyMsgEndpointUri", you have defined the Uri as:

var MesgUri = "tcp://ServerName:nnnn/MyMsgEndpointUri"; 

in your server, Initialize the endpoint by:

RemotingServices.Marshal([singletonInstance], MesgURI);  

Instead of RegisterWellKnownServiceType();

also, in the class representing the singleton, remember to override the InitializeLifetimeService property with a null operation... or the singleton object will get Garbage collected at some point...

public override object InitializeLifetimeService() { return (null); }

From the server, just call your singleton classes' static factory method to get access to that singleton instance... Do not use remoting calls at all...