Двойственные интерфейсы являются обычными интерфейсами СОМ, наследующими от IDispatch. Поскольку IDispatch является базовым интерфейсом, то он абсолютно совместим с полностью интерпретируемыми клиентами сценариев. В то же время этот интерфейс совместим вверх со средами, которые могут непосредственно связываться со статически определенным интерфейсом СОМ. Ниже приведено IDL-определение для двойственного варианта интерфейса DPrimeManager:
[object, dual, uuid(75DA6450-DD0F-11d0-8C58-0080C73925BA)] interface DIPrimeManager : IDispatch { [id(1), propget] HRESULT MinPrimeOnMachine( [out, retval] long *pval); [id(2), propput] HRESULT MinPrime([in] longval); [id(2), propget] HRESULT MinPrime([out, retval] long *pval); [id(3)] long GetNextPrime([in] long n); }
Заметим, что этот интерфейс наследует IDispatch, а не IUnknown. Также отметим, что данный интерфейс имеет атрибут [dual]. Этот атрибут заставляет сгенерированную библиотеку типов включить в себя диспетчерский вариант интерфейса, который совместим со средами, не поддерживающими двойственные интерфейсы. Атрибут [dual] относится к категории атрибутов [oleautomation] и также заставляет сгенерированную библиотеку типов добавлять ключи реестра для универсального маршалера во время выполнения RegisterTypeLib.
Если интерфейс определен как двойственный, то реализация методов IDispatch является тривиальной. Дело в том, что синтаксический анализатор библиотеки типов реализует два из четырех методов IDispatch. Если двойственный интерфейс был определен заранее, объекту необходимо на этапе инициализации просто загрузить библиотеку типов:
class PrimeManager : DIPrimeManager { LONG m_cRef; // СОМ reference count // счетчик ссылок СОМ ITypeInfo *m_pTypeInfo; // ptr. to type desc. // указатель на описание типов // IUnknown methods... // методы IUnknown...