Я занимаюсь разработкой надстройки для Excel, и в этом надстройке есть несколько доменов приложений. Мне нужно иметь доступ к некоторым общим данным по каждому домену приложений, поэтому я решил использовать кросс-домен синглтона. Я следовал тому, что было описано в этой теме:
http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx
Поскольку это надстройка Excel, мне пришлось немного изменить ее при создании домена приложений, содержащего синглтон, чтобы при поиске сборок использовался правильный базовый каталог. Ниже моя модифицированная версия:
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;
}
}
}
Вот моя реализация 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;
}
}
Как только я пытаюсь использовать метод get или set (я тоже пробовал свойство, но не получил ничего), я систематически получаю исключение:
Ном инконну. (Исключение из HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))
или на английском:
Неизвестное имя (Исключение из HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))
Маршаллинг отлично работает, когда я сохраняю встроенные типы, но, учитывая, что объект, к которому я хочу получить доступ (Microsoft.Office.Interop.Excel.Application), является COM-объектом, я боюсь, что это проблема.
Я очень плохо знаком с Remoting и Marshalling. Есть идеи? Это как-то связано с сериализацией COM-объекта?
Большое спасибо заранее!
Шон