I am developing an excel addin and in this addin there are several AppDomains. I need to have access to some shared data across each AppDomain so I decided to use a cross-AppDomain singleton. I followed what was described in this thread :
http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx
Because this is an excel addin, I had to modify it a little when creating the AppDomain that contains the singleton so that the correct base directory is used when searching for assemblies. Below is my modified version:
public class CrossAppDomainSingleton<T> : MarshalByRefObject where T : new()
{
private static readonly string AppDomainName = "Singleton AppDomain";
private static T _instance;
private static AppDomain GetAppDomain(string friendlyName)
{
IntPtr enumHandle = IntPtr.Zero;
mscoree.CorRuntimeHostClass host = new mscoree.CorRuntimeHostClass();
try
{
host.EnumDomains(out enumHandle);
object domain = null;
while (true)
{
host.NextDomain(enumHandle, out domain);
if (domain == null)
{
break;
}
AppDomain appDomain = (AppDomain)domain;
if (appDomain.FriendlyName.Equals(friendlyName))
{
return appDomain;
}
}
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
host = null;
}
return null;
}
public static T Instance
{
get
{
if (null == _instance)
{
AppDomain appDomain = GetAppDomain(AppDomainName);
if (null == appDomain)
{
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
appDomain = AppDomain.CreateDomain(AppDomainName, null, baseDir, null, false);
}
Type type = typeof(T);
T instance = (T)appDomain.GetData(type.FullName);
if (null == instance)
{
instance = (T)appDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
appDomain.SetData(type.FullName, instance);
}
_instance = instance;
}
return _instance;
}
}
}
Here is my implementation of the CrossAppDomainSingleton :
public class RealGlobal : CrossAppDomainSingleton<RealGlobal>
{
//ExcelApp Value Shared
private Microsoft.Office.Interop.Excel.Application s_excelApp = null;
public Microsoft.Office.Interop.Excel.Application GetExcelApp()
{
return s_excelApp;
}
public void SetExcelApp(Microsoft.Office.Interop.Excel.Application app)
{
s_excelApp = app;
}
}
Once I try to use either the get or set method (I tried a property also but got no further), I systematically get an exception:
Nom inconnu. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))
or in English: Unknown Name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))
Marshalling works fine when I keep built-in types, but given that the object I want to access (Microsoft.Office.Interop.Excel.Application) is a COM object, I fear that this is the problem.
I'm very new to Remoting and Marshalling. Any ideas? Does it have something to do with the serialization of a COM object?
Many thanks in advance! Sean