TurboBL

Содержание

Назначение

Краткий экскурс в механизм вызова методов

Для всех

Что происходит внутри 1С, когда мы пишем спр.ТекущийЭлемент()?

1С преобразует имя метода ТекущийЭлемент в соответствующий ему номер, и вызывает метод объекта по номеру. НО, клинические исследования показали, что для ЛЮБОГО объекта 1С используется один алгоритм такого преобразования, реализованный "В ЛОБ", и котрый заключатся в простом последовательном переборе всех имен методов объекта и сравнении их с искомым. Соответственно, чем больше номер метода, тем большее время занимает такой поиск. Например, для того же "ТекущийЭлемент" перед реальным вызовом функции происходит перебор 88 названий методов.

Аналогично и для свойств объектов.

Для знакомых с "Rainbow"

Как известно, для поиска номера метода применяется

virtual int CBLContext::FindMethod(const char* name);

Как оказалось, НИ В ОДНОМ из объектов 1С данный метод не переопределен. Перехват вызова функций различных объектов показал лень и мягко говоря, не вполне компетентность людей, писавших этот код.

Вобщем, когда вызывается FindMethod, из него вызываются: GetNMethods(), GetMethodName(i,0), GetMethodName(i,1) т.е. FindMethod работает примерно так:

for(int i=0;i<GetNMethods();i++)
{
    if(!stricmp(name,GetMethodName(i,0))
        return i;
    if(!stricmp(name,GetMethodName(i,1))
        return i;
}
return -1;

Понятно, хотелось добиться универсальности и простоты, что и достигнуто. Но при этом: - Некомпетентность: GetNMethods можно вынести из цикла. - Лень: не зря же FindMethod виртуальная, почему же она не переопределена ни в одном из наследуемых классов для более оптимального поиска?

Аналогичная ситуация и с FindProp.

Цель компоненты

Дабы устранить досадную оплошность разработчиков 1С в отношении поиска методов и свойств была создана ВК TurboBL, которая включена в 1С++. Суть ее работы в следующем: оптимизация алгоритма преобразования имен методов/свойств в их номера.

Попутно сделана возможность обращаться к методам и переменным модулей ГрупповыхКонтекстов.

Как использовать

ЗагрузитьВнешнююКомпоненту("1cpp.dll");

Вот практически и все.

Более никаких изменений в существующем коде конфигурации не требуется. При загрузке компонента берет на себя всю работу по поиску номеров методов и свойств объектов 1С.

Вызов методов модулей групповых контекстов

Да!!! Свершилось!!!

Теперь можно через контекст обратится к методам и переменным модуля контекста.

Например:

конт=0;
ОткрытьФорму("Справочник.Товары",конт);
конт.Печать();
//где Печать() - процедура в модуле     ФормыСписка справочника.

или например:
// в модуле проведения дока
Процедура ЭтоДокСТоваром()
    возврат 1;
КонецПроцедуры;
Процедура ОбработкаПроведения(парам)
    глНекаяГлобФункция(Контекст);
    ....

// В ГМ:
Процедура глНекаяГлобФункция(Конт)
    Если Конт.ЭтоДокСТоваром()=1
    .......

Дополнительные методы контекстов

__ВызыватьМетодыКакСобытия / __CallMethodsAsEvents

Синтаксис:

__ВызыватьМетодыКакСобытия(<Флаг>)

Параметр:

Флаг - необязательный параметр. Число: 0 - отключает, 1 - включает вызов методов как событий.

Возвращает:

Предыдущее установленное значение.

Описание:

Вызов методов как событий влияет на установку номера строки для таблиц, расположенных на форме контекста, а также на подключение таблиц-шаблонов для объектов типа "Таблица", используемых в этом контексте (метод Таблица.ИсходнаяТаблица()).

Вызов метода влияет только на тот контекст, для которого он вызван. До вызова этого метода соответствующий ему флаг установлен в <1>.

Вызов метода (процедуры или функции) контекста может иметь разный результат в зависимости от того, был ли этот метод вызван из другого метода контекста, либо этот же метод вызван извне, например, по нажатию кнопки на форме. Например, для метода СообщитьНомерСтроки():

Процедура СообщитьНомерСтроки()
        Сообщить(тзНаФорме.НомерСтроки());
КонецПроцедуры

Процедура СменитьИСообщить()
        тзНаФорме.ПолучитьСтрокуПоНомеру(1);
        СообщитьНомерСтроки();
КонецПроцедуры

Вызов же того же метода контекста извне может иметь даже более непредсказуемый результат:

Процедура СменитьИСообщитьДляКонтекста(Конт)
        Конт.тзНаФорме.ТекущаяСтрока(2);
        Конт.тзНаФорме.ПолучитьСтрокуПоНомеру(1);
        Конт.СообщитьНомерСтроки();
КонецПроцедуры

В результате вызова данной процедуры может вывестись как 1, так и 2. В зависимости от версии TurboBL (или 1С++), которую вы используете.

Для устранения данной неоднозначности и был добавлен метод групповых контекстов __ВызыватьМетодыКакСобытия(). Результатом вызова

Конт.__ВызыватьМетодыКакСобытия(0);
СменитьИСообщитьДляКонтекста(Конт);
Конт.__ВызыватьМетодыКакСобытия(1);
СменитьИСообщитьДляКонтекста(Конт);

будет

1
2