Добавить в цитаты Настройки чтения

Страница 180 из 372

                 //IUnknown

                 STDMETHODIMP Querylnterface(REFIID riid, void** pIFace);

                 STDMETHODIMP_(ULONG)AddRef();

                 STDMETHODIMP_(ULONG)Release();

                 //IClassFactory

                 STDMETHODIMP LockServer(BOOL fLock);

                 STDMETHODIMP Createlnstance(LPUNKNOWN pUnkOuter,

                        REFIID riid, void** ppv);

private:

                 ULONG m_refCount; // Счетчик числа сылок на объект

};

#endif

Здесь стандартным образом объявлены конструктор, деструктор, три метода интерфейса IUnknown и два метода интерфейса IClassFactory. Семантика всех этих методов уже была изложена ранее. Дополнительно нужно пояснить смысл параметров методов LockServer и Createlnstance.

Параметр fLock принимает значение TRUE — заблокировать сервер, или FALSE — разблокировать сервер. Сервер ведет подсчет всех блокировок, установленных всеми его клиентами, и разрешает выгрузить себя из памяти, если только не осталось активных объектов и общий счет блокировок в памяти равен нулю.

Первый параметр метода CreateInstance используется только при агрегации, которая обсуждалась ранее. Именно, если класс CоBооk проектируется с возможностью его агрегации в другой СОМ класс (класс CоBооk готов предоставить возможность другому классу выдавать интерфейсы класса v за свои), то через параметр pUnkUuter (тип которого определяется в <unknwn.h> как typedef iunknown RPC_FAR * LPUKNOWN) он получает указатель интерфейса IUnknown того объекта, который его собрался агрегировать. Если CоBооk не проектировался с возможностью агрегации (так и есть в нашем случае), то он ожидает получение в этом параметре значения NULL, в противном случае тут будет выдана ошибка СLASS_E_NOAGGREGATION.

Второй параметр метода CreateInstance задает ссылку на идентификатор желаемого интерфейса, а третий возвращает запрошенный интерфейс (если он имеется).

Реализация фабрики класса CoBookFactory для класса CоBооk представлена ниже.

//////////////////////////////////////////////////

// CoBookFactory.срр: реализация класса CoBookFactory —

// фабрики класса для класса CoBook.

//////////////////////////////////////////////////

#include "CoBookFactory.h"

extern ULONG g_lockCount; // Счетчик блокировок сервера в памяти extern ULONG

g_objCount; // Счетчик активных объектов

//////////////////////////////////////////////////

// Конструктор и деструктор

//////////////////////////////////////////////////

CoBookFactory::CoBookFactory()

{

        m_refCount = 0;

        g_objCount++;

}

CoBookFactory::~CoBookFactory()

{

         g_obj Count--;

}

//IUnknown

STDMETHODIMP_(ULONG) CoBookFactory::AddRef()

{

         return ++m_refCount;

}

STDMETHODIMP_(ULONG) CoBookFactory::Release()

{

         if (--m_refCount == 0)

         {

                   delete this;

                   return 0;

          }

          else

                   return m_refCount;

}

STDMETHODIMP CoBookFactory::Querylnterface(REFIID riid, void** ppv)

{

          if(riid == IID_IUnknown)

          {

                   *ppv = (IUnknown*)this;

          }

          else if(riid == IID_IClassFactory)

          {

                   *ppv = (IClassFactory*) this;

          {

          else

          {

                    *ppv = NULL;

                    return E NOINTERFACE;

           }





           ((IUnknown*)(*ppv)) — > AddRef();

           return S OK;

}

//ICiassFactory

 STDMETHODIMP CoBookFactory::Createlnstance(

            LPUNKNOWN pUnkOuter, REFIID riid, void** ppv)

{

            if(pUnkOuter!= NULL)

            {

                     return СLASS_E_NOAGGREGATION;

            }

            CoBook* pBookObj = NULL;

            HRESULT hr;

            pBookObj = new CoBook;

            hr = pBookObj —> QueryInterface (riid, ppv);

            if (FAILED(hr))

                     delete pBookObj;

             return hr;

}

STDMETHODIMP CoBookFactory::LockServer(BOOL fLock)

{

             if (fLock)

                      ++g_lockCount;

            else

                      --g_lockCount;

            return S_OK;

}

В конструкторе обнуляется счетчик ссылок на фабрику класса — член класса m ref count (как всегда при создании любого объекта СОМ) и увеличивается на единицу глобальный счетчик числа активных объектов данного сервера (g objCount).

В деструкторе на единицу уменьшается глобальный счетчик активных объектов данного сервера.

Реализация методов интерфейса IUnknown стандартная и уже обсуждалась ранее.

Перейдем теперь к обсуждению реализации методов интерфейса IClassFactory и начнем с метода CreateInstance.

Во-первых, не предполагается агрегация класса CоBооk. В связи с этим выдается ошибка CLASS_E_NOAGGREGATION, если первый параметр не равен NULL.

В следующих строках кода и проявляется связь данной фабрики класса именно с классом CоBооk. Создается экземпляр класса CоBооk и запрашивается указатель на некоторый интерфейс этого класса:

CoBook* pBookObj = NULL;

HRESULT hr;

pBookObj = new CoBook;

hr = pBookObj — > QueryInterface(riid, ppv);

При неудаче получения интерфейса, созданный объект уничтожается.

В методе LockServer глобальный счетчик блокировок сервера в памяти увеличивается или уменьшается на единицу в зависимости от значения параметра fLock.

Совершенно аналогично определяется и реализуется фабрика класса CoJournalFactory для кокласса СоJournal.

//////////////////////////////////////////////////

// СоJournalFactory.h: заголовочный файл для класса

// CoJournaiFactory — фабрики класса для класса CoJournal

//////////////////////////////////////////////////

#ifndef _CoJournalFactory_

#define _CoJournalFactory

#include "CoJournal.h"

class CoJournalFactory: public IClassFactory

{

public:

           CoJournalFactory ();

           virtual ~CoJournalFactory();

           //IUnknown

           STDMETHODIMP Querylnterface(REFIID riid, void** pIFace);

           STDMETHODIMP_(ULONG)AddRef();

           STDMETHODIMP_(ULONG)Release();

           //IClassFactory

           STDMETHODIMP LockServer(BOOL fLock);

           STDMETHODIMP Createlnstance(LPUNKNOWN pUnkOuter,

                           REFIID riid, void** ppv);

private:

           ULONG m_refCount;

};

#endif

И теперь реализация фабрики класса СоJournalFactory для класса CoJournal.