Иллюстрированный самоучитель по Visual Studio .NET

Фабрика классов

Логика функционирования нашего проекта (типа клиент-сервер) вырождена, то есть излишне упрощена, так как мы хотели показать лишь основную нить алгоритма использования СОМ-объектов. Обычно в рамках этого алгоритма присутствует так называемая фабрика классов – специальный класс на стороне сервера, который реализует функциональность уже существующего и зарегистрированного в библиотеке СОМ интерфейса 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; };
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.