Фабрика классов
Логика функционирования нашего проекта (типа клиент-сервер) вырождена, то есть излишне упрощена, так как мы хотели показать лишь основную нить алгоритма использования СОМ-объектов. Обычно в рамках этого алгоритма присутствует так называемая фабрика классов – специальный класс на стороне сервера, который реализует функциональность уже существующего и зарегистрированного в библиотеке СОМ интерфейса iciassFactory.
Фабрики классов – это объекты СОМ создающие другие объекты сервера. Их цель – создать объект определенного типа, который однозначно задан своим CLSID. Каждый СОМ-объект должен в соответствии со стандартом иметь связанную с ним фабрику классов, которая ответственна за его создание. Так, в нашем случае мы должны иметь фабрику классов, способную воспроизводить любое требуемое клиентами количество объектов класса CoSay.
Интерфейс iciassFactory имеет всего два метода: Createlnstance и LockServer. Первый необходим для того, чтобы динамически создавать произвольное количество объектов тех классов (CLSID), которые живут в доме DLL СОМ-сервера, а второй – для того, чтобы запретить или разрешить системе выгружать сервер из памяти. Это позволяет пользователю гибко управлять необходимыми ресурсами.
Если СОМ-объект пока не нужен клиентскому приложению, но вскоре может понадобиться, то, вызвав метод LockServer с параметром TRUE, клиент может запретить выгрузку из памяти DLL-сервера, несмотря на то что счетчик числа пользователей ее объектами равен нулю. Если в течение какого-то времени не предвидится использование СОМ-объектов, то клиент может вызвать метод LockServer с параметром FALSE, разрешив тем самым выгрузку DLL-сервера из памяти.
Для реализации этой функциональности вновь откройте проект СОМ-сервера My с от и в файл МуСоm.срр добавьте две глобальные переменные:
//====== Счетчик числа блокировок DLL ULONG gLockCount; //====== Счетчик числа пользователей СОМ-объектами ULONG gObjCount;
В этот же файл введите новую функцию, которую будет экспортировать наша DLL:
STDAPI DllCanUnloadNow() { //====== Если счетчики нулевые, то мы позволяем //====== системе выгрузку DLL-сервера returnIgLockCount && IgObjCount? S_OK: S_FALSE; }
В конструктор класса coSay добавьте код, увеличивающий счетчик числа пользователей объектом Со Say:
gObjCount++;
А в деструктор – уменьшающий:
gObjCount--;
Важным шагом, о котором, тем не менее, легко забыть, является своевременная коррекция файла MyCom.def. Вставьте в конец этого файла строку:
DllCanUnloadNow PRIVATE
Которая добавляет в список экспортируемых функций еще один элемент. В файл MyCom.h добавьте декларацию нового класса CoSayFactory, реализующего интерфейс iclassFactory. Отметьте, что он произведен от интерфейса iClassFactory, который, как и положено, имеет родителя Iunknown. Вы помните, что на плечи класса ложится бремя реализации всех методов своих предков. По той же причине мы вновь заводим счетчик числа пользователей классом (m_ref):
//====== Фабрика классов СОМ DLL-сервера class CoSayFactory: public IClassFactory { public: CoSayFactory(); virtual ~CoSayFactory(); // lUnknown HRESULT _ stdcall Querylnterface(REFIID riid, void** ppv); UbONG _ stdcall AddRefO; ULONG _ stdcall Release(); // IClassFactory HRESULT _ stdcall Createlnstance(LPUNKNOWN pUnk, REFIID riid, void** ppv); HRESULT _ stdcall LockServer(BOOL bLock); private: ULONG m_ref; };