I'm working on a class which will provide a single instance across all clients on the same workstation (a 'super-singleton', to coin a phrase). In order to do this, the (super-)singleton class needs to run as a server in a separate AppDomain. Each client requesting an instance actually gets handed a reference to the existing instance, or if no instance has been created the first instance is created.
A couple of prerequisites.
#1. The application clients shouldn't know anything regarding the internal remoting architecture. They should simply be able to instantiate a class and use it as normal. This will provide convenience for application developers whose familiarity with class construction will be limited to basic OO concepts. Application devleopers should not need to be familiar with .NET remoting details and infrastructure.
#2. The (super)-singleton class must be sharable among legacy VB6 applications, as well as newer .NET applications. This puts emphasis on pre-requisite #1. VB6 developers are likely to know how to instantiate the .NET class, but not likely to know how to access a remoted object (if this is even possible).
I've attached my solution. Basically, the class Singleton is a normal class instance. Each client (.NET or ActiveX) will create its own instance of this class. However, this class encapsulates the .NET remoting code which results in another inner class, SingleCore, being either created (initially) or accessed as a remote singleton server class. If you run multiple instances of SingletonClient you'll see that this works perfectly. Each SingletonClient gets its own instance of Singleton (see form caption), however each Singleton is sharing the same SingleCore class (see textbox). If you dig down into SingletonClients\bin\Release, you can run both the .NET and VB6 executables side-by-side and you'll see that these do in fact share the same SingleCore instance.
However, one of the primary reasons for creating this centralized super-singleton is that all clients need notification when any one client makes a call into the Singleton class. Here's where my model starts breaking down. I've had extreme trouble trying to implement either Events or a Callback interface. Either of these approaches require Serialization. But when serializing, the serialized class loses the reference to any event handlers which are registered for its events. Since events only fire if one or more handlers are registered, my events never fire. Basically, SingleCore will fire events into each Singleton class. However, while that event is firing, Singleton is in a state of serialization and it doesn;t find any handlers registered. When the call unwinds, and Singleton is returned to its pre-serialized state, all handlers are again visible, however they won't fire because they're supposed to be fired inside the event handler for the SingleCore event.
I don't see any way out of this corner. If you can suggest how I can accomplish this, I'll be most grateful. My code is presented below the signature. I don't see any way to include an attachment on this forum. If you'd like to pick up the attachment, yoiu can find it on the newsgroup at microsoft.public.dotnet.framework.remoting, subject: How do I get Events from Remote Class Instance
Thanks!
- Joseph Geretz -
SingleCore:
---------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Singleton
{
[ComVisible(true)]
public class SingleCore : MarshalByRefObject
{
private string m_InstanceID;
private Singleton m_Singleton;
{
[ComVisible(true)]
public class SingleCore : MarshalByRefObject
{
private string m_InstanceID;
private Singleton m_Singleton;
private SingleCore()
{
m_InstanceID = Guid.NewGuid().ToString();
}
{
m_InstanceID = Guid.NewGuid().ToString();
}
public string InstanceID
{
get
{
return m_InstanceID;
}
}
{
get
{
return m_InstanceID;
}
}
public void Register(Singleton S)
{
m_Singleton = S;
}
}
}
{
m_Singleton = S;
}
}
}
Singleton:
--------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace Singleton
{
[ComVisible(true)]
public class Singleton
{
private SingleCore m_Instance;
private string m_InstanceID;
{
[ComVisible(true)]
public class Singleton
{
private SingleCore m_Instance;
private string m_InstanceID;
public Singleton()
{
m_InstanceID = Guid.NewGuid().ToString();
{
m_InstanceID = Guid.NewGuid().ToString();
GetValidServerCore();
}
}
public string CoreInstanceID
{
get
{
try
{
return m_Instance.InstanceID;
}
catch
{
GetValidServerCore();
return m_Instance.InstanceID;
}
}
}
{
get
{
try
{
return m_Instance.InstanceID;
}
catch
{
GetValidServerCore();
return m_Instance.InstanceID;
}
}
}
public string InstanceID
{
get { return m_InstanceID; }
set { m_InstanceID = value; }
}
{
get { return m_InstanceID; }
set { m_InstanceID = value; }
}
private void GetValidServerCore()
{
try
{
TcpChannel Channel = new TcpChannel(13101);
ChannelServices.RegisterChannel(Channel, false);
{
try
{
TcpChannel Channel = new TcpChannel(13101);
ChannelServices.RegisterChannel(Channel, false);
RemotingConfiguration.RegisterWellKnownServiceType
(typeof(SingleCore),
"Singleton.SingleCore",
WellKnownObjectMode.Singleton);
}
catch { }
(typeof(SingleCore),
"Singleton.SingleCore",
WellKnownObjectMode.Singleton);
}
catch { }
m_Instance = (SingleCore)Activator.GetObject(typeof(SingleCore), "tcp://localhost:13101/Singleton.SingleCore");
}
}
}
}
}

How do I get Events from Remote Class Instance?