Интернет-журнал "Домашняя лаборатория", 2007 №6 - Усманов
#include "CoBook.h"
class CoBookFactory: public iciassFactory
{
public:
// Конструктор и деструктор
CoBookFactory ();
virtual ~CoBookFactory();
//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.
//////////////////////////////////////////////////
// СоJournalFactory.срр: реализация фабрики класса СоJournalFactory
// для кокласса CoJournal
//////////////////////////////////////////////////
#include "СоJournalFactory.h"
extern ULONG g_lockCount;
extern ULONG g_objCount;
//////////////////////////////////////////////////
// Конструктор и деструктор
//////////////////////////////////////////////////
CoJournalFactory::СоJournalFactory ()
{
m_refCount = 0;
g_objCount++;
}
CoJournalFactory::~CoJournalFactory()
{
g_obj Count-;
}
//IUnknown
STDMETHODIMP_(ULONG) CoJournalFactory::AddRef() {
return ++m_refCount;
}
STDMETHODIMP_(ULONG) CoJournalFactory::Release()
{
if (-m_refCount == 0)
{
delete this;
return 0;
}
else
return m refCount;
}
STDMETHODIMP CoJournalFactory::Querylnterface(REFIID riid, void** ppv)
{
Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Интернет-журнал "Домашняя лаборатория", 2007 №6 - Усманов, относящееся к жанру Газеты и журналы / Сделай сам / Хобби и ремесла. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.


