Как получить описание объекта

Для получения описания COM-объектов, создаваемых компонентой, используется объект Reflector. Он является независимой частью компоненты и создаётся как отдельный объект.

С помощью Reflector’а можно:

  • Получить имя класса (имя реализуемого интерфейса) как оно описано в библиотеке типов.

  • Получить набор полей объекта.

  • Узнать, есть ли у объекта указанное свойство.

  • Узнать тип значения у свойства.

Для примеров будем использовать Box и DynamicContent для первого титула УПД 970.

Функция ПолучитьЯщик()
    Возврат ИмплементацияПолучитьЯщик(); // Подробнее в https://developer.kontur.ru/Docs/Diadoc/COM/HowTo/start/authorization.html
КонецФункции


Функция ПолучитьКонтентПродавца(T, F, V)
    dd_Box = ПолучитьЯщик();

    dd_SendTask = dd_Box.CreatePackageSendTask2();
    dd_DocumentToSend = dd_SendTask.AddDocument(T, F, V);
    Возврат dd_DocumentToSend.Content;
КонецФункции


Функция ПолучитьКонтентПродавцаУПД970()
    Возврат ПолучитьКонтентПродавца("UniversalTransferDocument", "СЧФДОП", "utd970_05_03_01");
КонецФункции


Функция ПолучитьОписаниеОбъекта(dd_Object)
    dd_Reflector = ПолучитьReflector();

    Возврат dd_Reflector.Describe(dd_Object);
КонецФункции

Получение имени интерфейса

Процедура ПолучитьИмяИнтерфейса(dd_Object)
    dd_TypeDesc = ПолучитьОписаниеОбъекта(dd_Object);

    Возврат dd_TypeDesc.GetInterfaceName();
КонецПроцедуры


Процедура Пример()
    dd_Box = ПолучитьЯщик();
    Сообщить(ПолучитьИмяИнтерфейса(dd_Box)); // "IBox"

    dd_Content = ПолучитьКонтентПродавцаУПД970();

    Сообщить(ПолучитьИмяИнтерфейса(dd_Content));                // "UniversalTransferDocument"
    Сообщить(ПолучитьИмяИнтерфейса(dd_Content.Signers));        // "Signers"
    Сообщить(ПолучитьИмяИнтерфейса(dd_Content.Signers.Signer)); // "IValueCollection"
КонецПроцедуры

Для статически писанных интерфейсов их имя будет начинаться с I (в примере IBox для переменной dd_Box и IValueCollection для dd_Content.Signers.Signer).

Для DynamicContent имя интерфейса вычисляется во время работы программы и зависит от имени типа в XSD схеме.

Получение имён свойств объекта

Процедура НапечататьИменаСвойств(dd_Object)
    dd_TypeDesc = ПолучитьОписаниеОбъекта(dd_Object);

    Для Каждого PropertyName Из dd_TypeDesc.GetPropertiesNames() Цикл
        Сообщить(PropertyName);
    КонецЦикла;
КонецПроцедуры


Процедура Пример()
    dd_Box = ПолучитьЯщик();
    НапечататьИменаСвойств(dd_Box);

    dd_Content = ПолучитьКонтентПродавцаУПД970();
    НапечататьИменаСвойств(dd_Box);
КонецПроцедуры

Проверка наличия свойства

Функция ЕстьСвойство(dd_Object, PropertyName)
    dd_TypeDesc = ПолучитьОписаниеОбъекта(dd_Object);

    Возврат dd_TypeDesc.HasProperty(PropertyName);
КонецФункции


Процедура Пример()
    dd_Box = ПолучитьЯщик();

    Сообщить(ЕстьСвойство(dd_Box, "Guid"));             // "Да"
    Сообщить(ЕстьСвойство(dd_Box, "gUiD"));             // "Нет"
    Сообщить(ЕстьСвойство(dd_Box, "NotExistProperty")); // "Нет"
    Сообщить(ЕстьСвойство(dd_Box, "Id"));               // "Нет"
КонецПроцедуры

Можно заметить, что проверка регистрозависимая и устаревшие и скрытые поля также считаются отсутствующими.

Получение типа свойства

Функция ПолучитьТипСвойства(dd_Object, PropertyName)
    dd_TypeDesc = ПолучитьОписаниеОбъекта(dd_Object);

    Возврат dd_TypeDesc.GetPropertyType(PropertyName);
КонецФункции


Процедура Пример()
    dd_Box = ПолучитьЯщик();

    Сообщить(ПолучитьТипСвойства(dd_Box, "Guid"));                // "VT_BSTR"
    Сообщить(ПолучитьТипСвойства(dd_Box, "NotExistProperty"));    // ""
    Сообщить(ПолучитьТипСвойства(dd_Box, "DepartmentsTree"));     // "VT_PTR"
    Сообщить(ПолучитьТипСвойства(dd_Box, "IsTest"));              // "VT_BOOL"
    Сообщить(ПолучитьТипСвойства(dd_Box, "FnsRegistrationDate")); // "VT_DATE"
КонецПроцедуры

Получение описания методов объектов

Функция ПолучитьОписаниеМетодов(dd_Object)
    dd_TypeDesc = ПолучитьОписаниеОбъекта(dd_Object);

    Для Каждого MethodName Из dd_TypeDesc.GetMethodsNames() Цикл
        dd_MethodDesc = dd_TypeDesc.GetMethodDesc(MethodName);

        АргументыСтрокой = "";
        Для Каждого Arg Из dd_MethodDesc.Args Цикл
            АргументыСтрокой = АргументыСтрокой + Arg + ", ";
        КонецЦикла;
        ДлинаАргументов = СтрДлина(АргументыСтрокой);
        Если ДлинаАргументов > 2 Тогда
            АргументыСтрокой = Лев(АргументыСтрокой, ДлинаАргументов - 2);
        КонецЕсли;

        Сообщить(dd_MethodDesc.Name() + "(" + АргументыСтрокой + ") -> " + dd_MethodDesc.RetVal);
    КонецЦикла;
КонецФункции


Процедура Пример()
    dd_Box = ПолучитьЯщик();

    ПолучитьОписаниеМетодов(dd_Box);
КонецПроцедуры