Сущность технологии COM




Объекты имеют статический тип - часть 2


Использование переменной информации о состоянии при решении вопроса о том, удовлетворять или нет запрос QueryInterface (например, выдавать интерфейс INotBusy (не занят), только если количество внешних интерфейсных указателей меньше десяти).

Использование маркера доступа (security token) вызывающего объекта для решения, удовлетворять или нет запрос QueryInterface. Как будет объяснено в главе 6, на самом деле это не обеспечивает никакой реальной безопасности из-за протокола передачи (wire protocol), используемого СОМ.

Использование успешного захвата динамических ресурсов для решения вопроса о том, удовлетворять или нет запрос QueryInterface (например, выдавать интерфейс IHaveTonsOfMemory (у меня тонны памяти) только при успешном выполнении malloc(4096*4096)).

Эта последняя методика может быть до некоторой степени смягчена, если разработчик объекта желает поупражняться с выражением спецификации СОМ "barring catastrophic failure" (за исключением катастрофического сбоя).

Эти ограничения не означают, что два объекта одного и того же класса реализации не могут давать различные ответы "да/нет" при запросе одного и того же интерфейса. Например, класс может реализовать показанные ранее интерфейсы ICar, IBoat и IPlane, но может разрешить только одному интерфейсу быть использованным в каком-то определенном объекте. Эти ограничения также не означают, что объект не может использовать постоянную или временную информацию для решения вопроса о том, дать ли исходное "да" или "нет" для данного интерфейса. В примере для класса, который разрешает только один из трех интерфейсов, следующая идиома была бы вполне допустимой:

class СВР : public ICar, public IPlane, public IBoat { enum TYPE { CAR, BOAT, PLANE, NONE }; TYPE m_type; CBP(void) : m_type(NONE) { } STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { if (md == IID_ICar) { // 1st QI Initializes type of object // первая QI инициализирует тип объекта if (m_type == NONE) m_type = CAR; // only satisfy request if this object is a car // удовлетворяем запрос, только если данный объект // является car (автомобилем) if (m_type == CAR) *ppv = static_cast<ICar*>(this); else return (*ppv = 0), E_NOINTERFACE; } else if (md == IID_IBoat) { // similar treatment for IBoat and IPlane // IBoat и IPlane обрабатываются сходным образом } };

Из требования, чтобы множество поддерживаемых интерфейсов было статичным, следует простой вывод, что разработчикам объектов не разрешается создавать конструкции, состоящие из одного объекта, который дает два различных ответа "да/нет" на запрос определенного интерфейса. Одна из причин того, что иерархия типов объекта должна оставаться неизменной на всем протяжении своего жизненного цикла, состоит в том, что СОМ не гарантирует отправления всех клиентских запросов QueryInterface такому объекту в случае, когда к нему имеется удаленный доступ. Неизменность иерархии типов позволяет "заместителям" на стороне клиента (client-side proxies) кэшировать результаты QueryInterface во избежание чрезмерных обменов клиент-объект. Такая оптимизация очень важна для эффективности СОМ, но она разрушает конструкции, использующие QueryInterface для передачи динамической семантической информации вызывающему объекту.




Содержание  Назад  Вперед