Категория компонентов есть группа логически родственных СОМ-классов, которые разделяют общий ID категории, или CATID . Идентификаторы категории CATID – это GUID, записанные в реестре как атрибуты класса. Каждый класс может иметь два подключа: Implemented Categories и Required Categories (реализованные категории и нужные категории). Представим, что есть две категории компонентов: Simians и Mammals (приматы и млекопитающие). Каждая из этих двух категорий будет иметь уникальный CATID ( CATID_Simians и CATID_Mammals соответственно). Допустим, что класс Chimp является членом каждой из этих категорий, и тогда для Chimp ключ реестра Implemented Categories будет содержать в себе каждый GUID как отдельный подключ:
[HKCR\CLSID\{CLSID_Chimp}\Implemented Categories\{CATID_Mammals}]
[HKCR\CLSID\{CLSID_Chimp}\Implemented Categories\{CATID_Simians}]
Эти элементы реестра обычно добавляются во время саморегистрации. Каждая известная категория компонентов в системе имеет запись в разделе реестра HKEY_CLASSES_ROOT\Component Categories
Каждая категория имеет свой собственный уникальный подключ, названный как CATID . Под этим подключом каждая категория имеет одну или более именованных величин, содержащих текстовое описание этой категории. Например, двум показанным выше категориям понадобятся такие элементы реестра:
[HKCR\Component Categories\{CATID_Mammals}] 409="Bears live young"
[HKCR\Component Categones\{CATID_Simians}] 409="Eats Bananas"
Отметим, что в этом примере используется величина 409, являющаяся кодом локализации, или локальным идентификатором языка LCID (locale identifier), для U.S.English. Другая местная специфика может поддерживаться путем добавления дополнительных именованных величин.
Классы также могут указать, что они требуют от клиента функциональное назначение определенного типа. Обычно такая поддержка принимает вид узловых интерфейсов ( site interfaces ), которые клиент предоставляет активированному объекту. Для того, чтобы разделить эти предоставляемые клиентом сервисы на категории, не зависящие от отдельного интерфейса, СОМ позволяет классам объявлять второй тип категорий ID; он может использоваться клиентами для гарантии того, что они не активировали компонент, который не могут должным образом принять. Рассмотрим следующие две категории сервисов, предоставляемых клиентом: CATID_HasOxygen и CATID_HasWater . Поскольку для выживания шимпанзе необходимы кислород и вода, разработчик Chimp должен объявить, что эти две категории сервисов, предоставляемых клиентом, необходимы для активации. Это делается с помощью подключей из Required Categories :
[HKCR\CLSID\{CLSID_Chimp}\Required Categories\{CATID_HasOxygen}]
[HKCR\CLSID\{CLSID_Chimp}\Required Categories\{CATID_HasWater}]
Кроме того, ID этих двух категорий следует внести в реестр под ключом HKEY_CLASSES_ROOT\Component Categories
Получив эти записи, сам клиент перед активацией должен убедиться в том, что он удовлетворяет запрошенным категориям. СОМ не обеспечивает согласование с клиентом.
Элементы категорий компонентов могут быть зарегистрированы либо с помощью явных функций реестра, либо с использованием предлагаемого СОМ менеджера категорий компонентов ( component category manager ). Этот менеджер категорий компонентов объявляется в СОМ как создаваемый СОМ-класс ( CLSID_StdComponentCategoriesMgr ), который реализует интерфейс ICatRegister для регистрации информации о категории и интерфейс ICatInformation для запроса информации о категории. Интерфейс ICatRegister позволяет библиотекам DLL сервера легко добавлять в реестр необходимые элементы:
[object, uuid(0002E012-0000-0000-C000-000000000046)]
interface ICatRegister : IUnknown {
// description info for a category
// описательная информация для категории
typedef struct tagCATEGORYINFO
{ CATID catid; LCID lcid; OLECHAR szDescription[128]; }
CATEGORYINFO;
// register cCts category descriptions
// регистрируем описания категории cCts
HRESULT RegisterCategories([in] ULONG cCts,
[in, size_is(cCts)] CATEGORYINFO rgCatInfo[]);
// unregister cCategories category descriptions
// отменяем регистрацию описаний категории
cCategories HRESULT UnRegisterCategories([in] ULONG cCategories,
[in, size_is(cCategories)] CATID rgcatid[]);
// indicate a class implements one or more categories
// показываем, что класс реализует одну или более категорий
HRESULT RegisterClassImplCategories([in] REFCLSID rclsid,
[in] ULONG cCategories,
[in, size_is(cCategories)] CATID rgcatid[]);
// deindicate a class implements one or more categories
// перестаем показывать, реализует класс одну или более категорий
HRESULT UnRegisterClassImplCategories([in] REFCLSID rclsd,
[in] ULONG cCategories,
[in, size_is(cCategories)] CATID rgcatid[]);
// indicate a class requires one or more categories
// показываем, что класс требует одну или более категорий
HRESULT RegisterClassReqCategories([in] REFCLSID rclsid,
[in] ULONG cCategories,
[in, size_is(cCategories)] CATID rgcatid[]):
// deindicate a class requires one or more categories
// перестаем показывать, требует ли класс одну или более категорий
Читать дальше