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
Главные модули ядра
обращаются друг к друг другу используя описанный механизм регистрации
объектов.
Для сокращения размера
кода операции получения объектов, помещены
- в части FrontEnd - в модуль fe_Connector
- в части BackEnd - в модуль 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()
получают объекты описанным образом.