Нужно сделать так, чтобы один COM-объект создавался при старте моего сервера и использовался всеми запросами к этому коклассу. Это возможно? (COM-сервер и клиент находятся в одном процессе)
Как альтернатива, можно чтобы создалось несколько COM-объектов, но мне нужно быть уверенным, что они все будут созданы в одном app domain.
Есть идеи?
Здравствуйте, Аноним, Вы писали:
А>Нужно сделать так, чтобы один COM-объект создавался при старте моего сервера и использовался всеми запросами к этому коклассу. Это возможно?
Напишите singleton-обертку для COM-объекта.
Re[2]: как создать COM-синглтон?
От:
Аноним
Дата:
07.06.11 08:19
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:
HL>Напишите singleton-обертку для COM-объекта.
Здравствуйте, Аноним, Вы писали:
А>Что ты имеешь в виду?
public static class ComSingleton
{
private static readonly Type type;
private static readonly Object instance;
static ComSingleton()
{
type = Type.GetTypeFromProgID("MyComLibrary.MyComServer", true);
instance = Activator.CreateInstance(type);
}
public static Object Instance
{
get { return instance; }
}
public static Type Type
{
get { return type; }
}
}
Смысл в том, чтобы заморачиваться с синглтон-поведением не в COM, а в шарпе.
Здравствуйте, Аноним, Вы писали:
А>Нужно сделать так, чтобы один COM-объект создавался при старте моего сервера и использовался всеми запросами к этому коклассу. Это возможно? (COM-сервер и клиент находятся в одном процессе) А>Как альтернатива, можно чтобы создалось несколько COM-объектов, но мне нужно быть уверенным, что они все будут созданы в одном app domain. А>Есть идеи?
Почему нельзя сделать COM-синглетон в exe (LocalServer), а на клиентах
использовать прокси для доступа к нему ?
Re[2]: как создать COM-синглтон?
От:
Аноним
Дата:
07.06.11 08:44
Оценка:
Здравствуйте, okman, Вы писали:
O>Почему нельзя сделать COM-синглетон в exe (LocalServer), а на клиентах O>использовать прокси для доступа к нему ?
Таковы условия задачи. Добавочный процесс создавать нельзя.
Здравствуйте, bugmenot, Вы писали:
B>будет по одному экземпляру объекта на каждый app domain, насколько я понимаю.
Это не рабочий код, а идея.
Если предполагается использование нескольких доменов, то можно создать домен с заранее определенным именем, в нем создать экземпляр COM-объекта, а из обертки получать бы прокси к этому экземпляру.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, okman, Вы писали:
O>>Почему нельзя сделать COM-синглетон в exe (LocalServer), а на клиентах O>>использовать прокси для доступа к нему ?
А>Таковы условия задачи. Добавочный процесс создавать нельзя.
Значит, нужно COM-сервер должен использовать разделяемые между процессами данные,
чтобы выглядеть логически эквивалентно синглетону.
Например, через файлы, отображаемые в память или секции данных, помеченные
соответствующим атрибутом.
Не знаю, как это делается в .NET, но в Win32 — довольно просто.
Здравствуйте, bugmenot, Вы писали: B>Как?
Примерно вот так:
1) хост:
Скрытый текст
public class SingletonHost<T> : MarshalByRefObject
where T : MarshalByRefObject, new()
{
private static readonly T instance;
static SingletonHost()
{
instance = (T)Activator.CreateInstance(typeof(T));
}
public T Instance
{
get { return instance; }
}
}
2) клиент:
Скрытый текст
public class SingletonClient<T> : IDisposable
where T : MarshalByRefObject
{
private const String Mutex_Name = "CrossDomainSingleton";
private const String Host_Domain_Name = "SingletonDomain";
private readonly Mutex mutex;
private IEnumerable<AppDomain> GetAppDomains()
{
IntPtr enumHandle;
var host = new mscoree.CorRuntimeHost();
host.EnumDomains(out enumHandle);
try
{
Object domain = null;
do
{
host.NextDomain(enumHandle, out domain);
if (domain != null)
yield return (AppDomain)domain;
}
while (domain != null);
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
}
}
public SingletonClient()
{
mutex = new Mutex(false, Mutex_Name);
}
public T Instance
{
get
{
mutex.WaitOne();
try
{
var hostDomain = GetAppDomains().SingleOrDefault(d => d.FriendlyName == Host_Domain_Name);
if (hostDomain == null)
hostDomain = AppDomain.CreateDomain(Host_Domain_Name);
var host = (SingletonHost<T>)hostDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName,
typeof(SingletonHost<T>).FullName);
return host.Instance;
}
finally
{
mutex.ReleaseMutex();
}
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(Boolean disposing)
{
if (disposed)
return;
if (disposing)
{
if (mutex != null)
mutex.Dispose();
}
disposed = true;
}
private Boolean disposed;
#endregion
}
Ну и всю работу с COM-объектом заворачиваете в какого-нибудь наследника MBR.
Выдрано из тестового проекта, поэтому доработать напильником.
Рекомендую еще погуглить на тему cross-domain singleton — это не единственный вариант реализации.
Здравствуйте, HowardLovekraft, Вы писали:
HL>Ну и всю работу с COM-объектом заворачиваете в какого-нибудь наследника MBR. HL>Выдрано из тестового проекта, поэтому доработать напильником.
HL>Рекомендую еще погуглить на тему cross-domain singleton — это не единственный вариант реализации.
А вот этот new mscoree.CorRuntimeHost(); откуда берется?
Здравствуйте, Аноним, Вы писали:
А>Нужно сделать так, чтобы один COM-объект создавался при старте моего сервера и использовался всеми запросами к этому коклассу. Это возможно? (COM-сервер и клиент находятся в одном процессе) А>Как альтернатива, можно чтобы создалось несколько COM-объектов, но мне нужно быть уверенным, что они все будут созданы в одном app domain. А>Есть идеи?
Смотрите на ExtensibleClassFactory
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
DECLARE_CLASSFACTORY_SINGLETON обычно используется для внепроцессных объектов, но работает и для внутрипроцессных. Вставьте этот макрос в объявление класса — и будет Вам счастье.
Но это, конечно, если COM-объект на C++ написан.