Copyright (c) Prolog Development Center SPb

Application Frame. Обмен информацией между модулями

Все модули  ядра (как FE, так и BE) являются объектами и поэтому простые обращения к ним как к модулям-классам не могут быть использованы.
Applicaiton Frame использует единый регистратор объектов, который является хранилищем именованных объектов. Объект в регистратор добавляется программным путем пользователем, когда этот объект создается. Объект в регистраторе хранится до тех пор, пока не будет удален оттуда пользователем программным путем.

Если используется конфигурация, в которой FrontEnd и BackEnd являются отдельными приложениями и они связываются по Http, то у каждого из приложений регистратор объектов свой, то есть FE и BE не могут "видеть" модули-обекты друг друга. Однако и в конфигурации моно-приложения FE и BE не пользуются возможностью контактировать с модулями-объектами друг друга через общий для них регистратор объектов.

Операции над регистром объектов

Регистратор объектов является составной частью пакета SpbVipTools\Packs\Logic\PzlSystem\OpenPzl\Packs\pzl.pack
Предикатами манипуляции с регистрацией объектов являются (в классе pzl.cl):

predicates % Object registration
    register:(string ObjectName,object Object).
    registerMulti:(string ObjectName,object Object).
    getObjectByName_nd:(string ObjectName)->object Object nondeterm.
    getNameByObject_nd:(object Object)->string ObjectNameLow nondeterm.
    getNameAndObject_nd:(string ObjectName,object Object) nondeterm (o,o).
    unRegister:(string ObjectName,object Object).
    unRegisterByName:(string ObjectName).
    unRegisterAllByNamePrefix:(string EntityPrefix). % unregister all entities with the Prefixed names
    unRegisterByObject:(object Object).
    unRegisterAll:().

Регистрация осуществляется просто путем присвоения имени объекту

        pzl::register(<имя объекта>, <объект>),

например, так:

    ...
   Tasks=fe_CoreTasks::new(This),
   pzl::register(fe_CoreTasks_C, Tasks),
    ...

Где fe_CoreTasks_C - имя объекта по соглашению.

Получение зарегистрированного объекта для последующих обращений также несложно:
    ...
    TasksObj=pzl::getObjectByName_nd(fe_CoreTasks_C)),
    Tasks=tryConvert(fe_CoreTasks,TasksObj),!,

    Tasks:foo(),
    ...

Конечно, здесь следует  обратить внимание на детерминизм такого преобразования.

Удалить объект из регистратора можно простой операцией

    ...
    pzl::unRegisterByName(fe_CoreTasks_C),
    ...

Использование регистра объектов в ллагин-компонентах

Механизм регистрации объектов может быть легко построен с использованием любого подхода к организации хранения данных, а не только с использованием пакета pzl.pack.
Использование пакета pzl.pack замечательно тем, что плагин-компоненты также используют пакет pzl.pack для работы с зарегистрированными объектами. Но самое главное - плагин-компоненты, будучи DLL в своей сущности, имеют доступ к хранилищу объектов главного приложения.
Это значит, что плагин-компоненты могут обращаться к объектам друг друга и к объектам главного приложения, используя единую базу зарегистрированных объектов.

Применение модулей-объектов  fe_Connector и be_Connector

Главные модули ядра обращаются друг к друг другу используя описанный механизм регистрации объектов.
Для сокращения размера кода операции получения объектов, помещены
Регистрация объектов ядра осуществляется при старте приложения в классах  Common\AppFrontEnd\frontEnd.pro и  Common\AppBackEnd\backEnd.pro, соответственно.
При этом используется следующий прием (на примере модуля-объекта fe_CoreTasks).

        pzl::register(string::concat(toString(This),fe_CoreTasks_C), Tasks)

То есть имя объекта при регистрации состоит из строкового имени класса в виде константы fe_CoreTasks_C, к которому приписывается слева строковое представление объекта (frontEnd или backEnd).

В пределах приложения ApplicationFrame это не является существенным приемом. Однако, имя в виду, что любая из частей ApplicaionFrame может сама быть плагин-компонентой в некотором приложении (в том числе, построенном на базе ApplicationFrame), добавление такого префикса делает имя каждого объекта уникальным в пределах одного приложения.

Наконец, в классе xe_Connector, который является родительским классом модулей ядра обращение к любому объекту ядра делается простым обращением с использованием предикатов

для FrontEnd
predicates
    fe_AppWindow:()->fe_MainWindow.
    fe_CoreTasks:()->fe_CoreTasks.
    fe_Tasks:()->fe_Tasks.
    fe_Tests:()->fe_Tests.
    be_Responses:()->be_Responses.
    fe_Dictionary:()->fe_Dictionary.

для BackEnd
predicates
    be_CoreTasks:()->be_CoreTasks.
    be_Tasks:()->be_Tasks.
    be_Tests:()->be_Tests.
    fe_Requests:()->fe_Requests.
    be_Options:()->be_Options.
    be_Dictionary:()->be_Dictionary.

При этом получение и преобразование объекта в  fe_Connector и be_Connector  делаются уже описанным образом, так, как это приведено ниже для объекта класса fe_CoreTasks

clauses
    fe_CoreTasks()=convert(fe_CoreTasks,GuiTasks):-
        GuiTasks=pzl::getObjectByName_nd(string::concat(toString(frontEnd_P),fe_CoreTasks_C)),!.
    fe_CoreTasks()=_:-
        exception::raise_User(string::format("Component % not Registered!",fe_CoreTasks_C)).

Отсюда может быть понятна запись следующего фрагмента кода

    setRibbonScriptFilesAndNameSpace(Dialog):-
        Future=be_Responses():createResponseReciever_async(be_TakeRibbonScriptFiles_C),
        fe_CoreTasks():getRibbonScriptFiles(),
        ...

Где
be_Responses() и fe_CoreTasks() получают объекты описанным образом.