Пример подписки на событие

Цель примера — при наступлении события выполнить, помимо самого обработчика события, набор методов из других подсистем; состав этих методов заранее неизвестен.

Элемент справочника Товары(Товары.Объект) имеет событие ПередЗаписью, в котором описан некоторый стандартный алгоритм количественного учета.

Если в проект добавляется подсистема ценового учета, то перед записью элемента справочника Товары необходимо выполнять ряд дополнительных действий, чтобы учесть изменение цены. Подсистема складского учета также потребует ряд собственных действий для учета товаров на складах.

Если каждый раз менять обработчик ПередЗаписью() элемента справочника Товары, это будет создавать лишние зависимости на другие подсистемы проекта.

Поэтому вы можете создать контракт КонтрактПодпискиПередЗаписью с методом ПередЗаписью() и реализовать его в каждой из перечисленных подсистем. А в обработчике ПередЗаписью() справочника Товары получить все реализации этого контракта, которые существуют в проекте, и выполнить их.

Модуль КонтрактПодпискиПередЗаписью.xbsl выглядит следующим образом.

@НаСервере
абстрактный метод ПередЗаписью(ПредыдущееЗначение: Товары.Данные, ПараметрыЗаписи: Товары.ПараметрыЗаписи)

В нем объявлен один метод — ПередЗаписью(). Его сигнатура совпадает с сигнатурой системного метода Товары.Объект.ПередЗаписью().

Описание общего модуля Подписка1.yaml, который реализует контракт, выглядит следующим образом.

ВидЭлемента: ОбщийМодуль
Ид: 264c4ca4-3acd-4118-8d07-ffe9a77e6097
ОбластьВидимости: ВПодсистеме
Имя: Подписка1
Окружение: КлиентИСервер
НастройкиТипа:
    Контракты:
        - КонтрактПодпискиПередЗаписью

Общий модуль Подписка1.xbsl из подсистемы ценового учета, в котором находится реализация метода контракта, выглядит следующим образом.

@НаСервере
@ВПроекте
@Реализация
метод ПередЗаписью(ПредыдущееЗначение: Товары.Данные, ПараметрыЗаписи: Товары.ПараметрыЗаписи)
    // Алгоритм учета изменения цены.    
;

Общий модуль Подписка2.xbsl из подсистемы складского учета, в котором находится вторая реализация метода контракта, выглядит следующим образом.

@НаСервере
@ВПроекте
@Реализация
метод ПередЗаписью(ПредыдущееЗначение: Товары.Данные, ПараметрыЗаписи: Товары.ПараметрыЗаписи)
    // Алгоритм складского учета.    
;

Модуль объекта справочника Товары, Товары.Объект.xbsl, выглядит следующим образом.

@Обработчик
метод ПерезЗаписью(ПредыдущееЗначение: Товары.Данные, ПараметрыЗаписи: Товары.ПараметрыЗаписи)
 
   // Собственный алгоритм справочника Товары.
    
   // Получить все реализации контракта КонтрактПодпискиПередЗаписью.
   пер ВсеПодписки = КонтрактПодпискиПередЗаписью.ПолучитьСервисы() 
 
   // Исполнить все реализации.
   для Подписка из ВсеПодписки  
      Подписка.ПередЗаписью(ПредыдущееЗначение, ПараметрыЗаписи)
   ;
;
В обработчике события ПередЗаписью сначала выполняется собственный алгоритм, а затем получаются все реализации контракта КонтрактПодпискиПередЗаписью, которые имеются в проекте. После этого у каждой из них вызывается метод ПередЗаписью().
Возможная проблема: В реальных проектах, которые разрабатываются разными командами программистов, нет гарантии, что все реализации будут исправно работать. Поэтому вызов каждой реализации лучше окружить перехватом исключений, чтобы неработоспособность одной реализации не сломала все приложение:
   // Исполнить все реализации.
   для Подписка из ВсеПодписки
      попытка  
        Подписка.ПередЗаписью(ПредыдущееЗначение, ПараметрыЗаписи)
      поймать Искл: Исключение 
        // обработка исключения
      ;
   ;