Pzl-Component: различия между версиями
Строка 99: | Строка 99: | ||
===The constant componentID_С=== | ===The constant componentID_С=== | ||
The constant сomponentID_С defines the identifier of the component, which must be unique if possible in the global sense. It means that two programs in the global information space (and we do not even mention one computer), which use the component with the same identifier, may be sure that they use exactly the same pzl-component. This may be reached by the using of the Microsoft company approach to identify MSCOM components. | The constant сomponentID_С defines the identifier of the component, which must be unique if possible in the global sense. It means that two programs in the global information space (and we do not even mention one computer), which use the component with the same identifier, may be sure that they use exactly the same pzl-component. This may be reached by the using of the Microsoft company approach to identify MSCOM components. | ||
To fit this the pzl-technology uses the | To fit this the pzl-technology uses the data structure with the functor uid: | ||
<vip> | <vip> | ||
uid( | uid( | ||
Строка 114: | Строка 114: | ||
core::unsigned8 Byte8). | core::unsigned8 Byte8). | ||
</vip> | </vip> | ||
and this is in reality the analogue of the structure core::nativeGuid of Visual Prolog system. | and this is in reality the analogue of the structure core::nativeGuid of the Visual Prolog system. | ||
The identifier componentID_С used in two cases: | The identifier componentID_С used in two cases: | ||
*It is the identifier, which is used to register the component in the Windows registry or(and) in the user controlled component registry file | *It is the identifier, which is used to register the component in the Windows registry or(and) in the user controlled component registry file | ||
Строка 122: | Строка 122: | ||
To make the learning process easier, there is another way to represent the identifier - the string form str(string). Naturally, the uniqueness is not provided in that case, but for the educational purposes we may sacrifice the glibal uniqueness and to control the uniaueness of the identifier on the given computer only. | To make the learning process easier, there is another way to represent the identifier - the string form str(string). Naturally, the uniqueness is not provided in that case, but for the educational purposes we may sacrifice the glibal uniqueness and to control the uniaueness of the identifier on the given computer only. | ||
As the result we get two | As the result we get two alternative forms to define identifier in the domain entityUID_D declaration: | ||
<vip> | <vip> | ||
entityUID_D= | entityUID_D= |
Версия 11:37, 31 января 2008
Автор: Виктор Юхтенко
The necessary conditions to acknowledge the class as the pzl-component
Any class, which creates an objects (which has an interface), may be acknowledged as the component if:
- The name of the interface and the name of the class are different;
- The interface of the class supports the interface pzlComponent;
- The interface of the class includes the constants declarations:
- componentID_C of pzlDomains::entityUID_D type
- componentAlias_C of string type
- componentRunAble_C of core::booleanInt type
- componentMetaInfo_C of core::namedValue*. type
- сomponentDescriptor_C of pzlDomains::pzlComponentInfo_D type
- The declaration of the class contains the only constructor new(object ExistingObject);
- The implementation of the class derives the class pzlComponent;
- The package declarations file (.PH) of the class includes the file "System\Packs\pzlcomponent\pzlcomponent.ph".
The examples of the parts of the component declarations and implementations are shown below.
Class declaration
- Contains the only constructor new:(object UsingObject). The name of the interface different from the name of the class.
class сomponentExample:iComponentExample constructors new:(object UsingObject). end class
'Interface of the Class
- Contains the qualifiyer supports pzlComponent and the declaration of constants
- componentID_C
- componentAlias_C
- componentRunAble_C=b_True
- componentMetaInfo_C
- componentDescriptor_C
interface iComponentExample supports pzlComponent open core constants componentDescriptor_C:pzlDomains::pzlComponentInfo_D=pzlDomains::pzlComponentInfo ( componentAlias_C, componentID_C, componentRunAble_C, componentMetaInfo_C ). componentID_C:pzlDomains::entityUID_D=pzlDomains::str("ComponentExample"). componentAlias_C="ExampleOfTheComponent". componentRunAble_C=b_True. componentMetaInfo_C:namedValue_List=[]. predicates show:(). end interface iComponentExample
'Class Implementation
- Contains the inharitance statement inherits pzlComponent and also contains the clause for the constructor new(UsingObject)
implement componentExample inherits pzlComponent clauses new(UsingObject):- ... clauses show():- ... end implement componentExample
The Package Header File ComponentExample.PH
- Contains the include file 'PzlComponent.ph statement
#requires ... #include @"System\Packs\pzlcomponent\pzlcomponent.ph" #include @"pfc\core.ph"
Interface pzlComponent
The Interface pzlComponent corresponds to the class pzlComponent and this makes the class to be the pzl-component. The class PzlComponent , binds the component with other parts of the pzl-system. Also Interface PzlComponent helps in getting the information regarding the component.
The following predicates supported by the Pzl-system
- getContainerVersion() - returns the information regarding the version of the container, where the given component placed
- getContainerName() - returns the name of the file, where the given component placed
- getClassInfo(className,classVersion) - returns the name and the version of the class pzlComponent
The other predicates of the interface PzlComponent:
- getComponentVersion()-> string
- getComponentID() -> entityUID_D
- getComponentAlias() -> string
- getComponentMetaInfo() -> namedValue*
- release
must be defined in the implementation of the base class of the component. Otherwise the exception is generated while the appropriate call.
Predefined constants of the base interface ob the pzl-component
The constant componentID_С
The constant сomponentID_С defines the identifier of the component, which must be unique if possible in the global sense. It means that two programs in the global information space (and we do not even mention one computer), which use the component with the same identifier, may be sure that they use exactly the same pzl-component. This may be reached by the using of the Microsoft company approach to identify MSCOM components. To fit this the pzl-technology uses the data structure with the functor uid:
uid( core::unsigned32 Unsigned, core::unsigned16 Short1, core::unsigned16 Short2, core::unsigned8 Byte1, core::unsigned8 Byte2, core::unsigned8 Byte3, core::unsigned8 Byte4, core::unsigned8 Byte5, core::unsigned8 Byte6, core::unsigned8 Byte7, core::unsigned8 Byte8).
and this is in reality the analogue of the structure core::nativeGuid of the Visual Prolog system. The identifier componentID_С used in two cases:
- It is the identifier, which is used to register the component in the Windows registry or(and) in the user controlled component registry file
- It is the identifier, which is used to register the component in the pzl-container
Because of the identifier in the form uid is combersome sequence of letters and figures, it is not convenient to use it while the learning of the pzl-technology.
To make the learning process easier, there is another way to represent the identifier - the string form str(string). Naturally, the uniqueness is not provided in that case, but for the educational purposes we may sacrifice the glibal uniqueness and to control the uniaueness of the identifier on the given computer only.
As the result we get two alternative forms to define identifier in the domain entityUID_D declaration:
entityUID_D= str(string); uid(unsined16,...).
Константа componentAlias_C (Условное имя)
Наряду с уникальным идентификатором, pzl-технология предоставляет воможность присвоить каждой компоненте условное, содержательное имя, являющееся строкой символов. Для этого выбранное имя должно быть присвоено константе ComponentAlias_C. Однако уникальность Условного Имени (Alias) не является жестким требованием.
Так, Вы можете создать несколько текстовых редакторов с различными свойствами, которые поддерживают одни и те же интерфейсы. Каждый из этих текстовых редакторов будет иметь уникальный идентификатор типа entityUID_D и, возможно каждый из них будет иметь свое имя базового класса. Но все они могут иметь одно и то же условное имя "Текстовый Редактор". Тогда Ваша программа (подчеркнем, не зная имени класса), может при создании экземпляра pzl-компоненты использовать имя "Текстовый Редактор" и будет создаваться экземпляр той компоненты, которая в данный момент зарегистрирована на Вашем компьютере. Перерегистрировав новый редактор, вместо старого, Ваша программа будет использовать новый редактор с другими свойствами.
Однако не следует забывать, что все коллизии, связанные с возможной неуникальностью условных имен, должны разрешаться программистом.
Условное имя может использоваться различными средствами pzl-технологии для идентификации компонент как на экране, так и в сообщениях об ошибках.
Константа componentRunable_C
Эта константа сообщает о возможности запуска данной компоненты путем вызова предиката spbRun:(string UserInfo). Предикат spbRun декларируетс в одноименном интерфейсе spbRun.
Соответственно, компонента должна поддерживать интерфейс spbRun, если возможность вызова предиката spbRun предусматривается.
Если интерфейс spbRun компонентой поддерживается, то константа componentRunable_C должна иметь значение core::b_true и core::b_false - если не поддерживается.
Предикат spbRun - это, по крайней мере, один предикат в pzl-компоненте, который может этой компонентой поддерживаться и имя этого предиката известно.
Предикат spbRun имеет единственный входной параметр UserInfo типа string, назначение которого определяется создателем компоненты.
Если данная компонента может быть вызвана с помощью предиката spbRun, это означает, что в приложении для данной компоненты всегда имеются условия, которые позволяют этой компоненте выполнить какую-то функциональную задачу.
Это несколько напоминает функцию раздела GOAL - точка начала работы программы, но в случае с предикатом spbRun этот предикат может быть вызван, а может быть и не вызван.
Если приложение основано на использовании графического пользовательского интерфейса (pfc/GUI или pfc/VPI), то возможность запуска компоненты предикатом spbRun может означать, что будет создана какая-то форма на экране и эта форма далее позволит сделать что-то значимое (не обязательно полезное).
Если пользовательский интерфейс не используется, то предикат spbRun может быть использован и для других целей по усмотрению программиста.
Предикат spbRun:(string UserInfo) объявлен в интерфейсе spbRun, где он является единственным. Если компонента поддерживает интерфейс spbRun, то это декларируется стандартным способом:
interface componentInterface supports pzlComponent supports spbRun constants ... ComponentRunable_C = b_true. ... end interface componentInterface
либо один из интерфейсов, поддерживаемых базовым интерфейсом компоненты, должен поддерживать интерфейс spbRun, как показано ниже
interface componentInterface supports pzlComponent supports textEditor constants ... componentRunable_C = b_true. ... end interface componentInterface interface textEditor supports spbRun ... end interface textEditor
Константа componentMetaInfo_C
Константа componentMetaInfo_C имеет тип core::namedValue* и представляет список именованных данных, относящихся к данной компоненте - метаинформация о компоненте.
pzl-Система никак эту метаинформацию не обрабатывает, но при соотвествующем запросе к контейнеру данные этого списка доступны программисту.
Если метаинформация о компоненте отсутствует, то константа componentMetaInfo_C все равно должна быть определена и должна представлять пустой список.
constants componentMetaInfo_C = [].
Константа Описания Компоненты сomponentDescriptor_C
Константа сomponentDescriptor_C включает описания важнейших свойств компоненты перечисленные выше:
- ComponentID_C,
- ComponentAlias_C,
- ComponentRunable_C
- ComponentMetainfo_C
Константа сomponentDescriptor_C соответствует домену pzlDomains::pzlComponentInfo_D, объявленному в интерфейсном файле pzlDomains:
pzlComponentInfo_D=pzlComponentInfo ( string Alias, entityUID_D ComponentID, booleanInt Runable, core::namedValue_List UserDefinedInfo ).
Пример описания констант pzl-компоненты
В реальной компоненте константы описания могут выглядеть так:
constants componentDescriptor_C:pzlDomains::pzlComponentInfo_D=pzlDomains::pzlComponentInfo ( componentAlias_C, componentID_C, componentRunAble_C, componentMetaInfo_C ). componentID_C:pzlDomains::entityUID_D=pzlDomains::str("ComponentExample"). componentAlias_C="ПримерКомпоненты". componentRunAble_C=b_True. componentMetaInfo_C:namedValue_List=[].
или так
constants componentDescriptor_C:pzlDomains::pzlComponentInfo_D=pzlDomains::pzlComponentInfo ( componentAlias_C, componentID_C, componentRunAble_C, componentMetaInfo_C ). componentID_C:pzlDomains::entityUID_D=pzlDomains::uid(0x5701809E,0x0453,0x43A2,0xB1,0x82,0x8F,0xAE,0x2A,0x6B,0xA5,0x63). componentAlias_C="PzlAboutDialog". componentRunAble_C=b_False. componentMetaInfo_C:namedValue_List= [ namedValue("CodeExporter",string("AboutExporter")) ].
Конструктор компоненты new:(object UsingObject)
Базовый класс pzl-Компоненты должен включать только один конструктор, имеющий формат new:(object UsingObject).
Здесь параметр UsingObject (что предполагает трактовку "С использованием объекта") не имеет никакого назначения и может быть использован автором pzl-Компоненты по своему усмотрению.
Например, в случае компоненты на базе GUI этот параметр может передавать объект типа window, соответствующий родительскому окну. Но если вызов конструктора в форме new(ParentWindow) автоматически преобразует тип window в тип object, то следует иметь в виду, что клауза конструктора, получит этот параметр именно как параметр типа object и непосредственное обращение к этому объекту невозможно.
Для обращения к объекту, переданному в виде параметра, необходимо привести параметр к типу, соответствующему возможному типу существующего объекта.
Например, в рассматриваемом случае с передачей объекта родительского окна для получения его высоты (height) надо привести объект ParentWindowAsObject в тип window:
clauses new(ParentWindowAsObject):- ParentWindow=convert(window,ParentWindowAsObject), WindowHeight=ParentWindow:getHeight(), ...
Особенности использования pzl-компонент как VIP-классов
Pzl-Компоненты, являясь обычными классами системы программирования Visual Prolog (VIP-классы), не требуют каких-либо специальных приемов программирования. Более того, при практическом программировании никакой разницы между использованием обычных VIP-классов и pzl-компонент нет. Тем не менее мы отметим здесь некоторые детали техники их созданиия и использования.
Создание pzl-компоненты
Создание pzl-компоненты возможно двумя способами:
- Специальными средствами pzl-технологии
- Стандартными средствами IDE (не рекомендуется)
Процедура создания pzl-компоненты стандартными средствами IDE не является рекомендуемой и приводится для разрешения коллизий в экстраординарных случаях
- Создать в проекте, являющемся pzl-контейнером новый класс в пакете, который будет всегда связан с этим классом
- При создании класса указать, что класс порождает объекты
- После создания создания класса вручную модифицировать код для обеспечения всех ранее
Компиляция проекта, содержащего созданную таким образом pzl-компоненту, может привести к генерации множества ошибок, если не "зарегистрирована" в проекте-контейнере.
Для регистрации pzl-компоненты в pzl-контейнере необходимо:
- В файле PzlConfig.i определить константу usePzl[ИмяКомпоненты]_C:boolean=true.
- В файле PzlConfig.pack в раздел % privately used packages добавить полное имя заголовочного файла пакета
#include @"ИмяФайлаКомпоненты.ph"
- В файле PzlConfig.pro:
- в список, возвращаемый предикатом getComponentIDInfo() добавить элемент вида
[ИмяБазовогоИнтерфейсаКомпоненты]::componentDescriptor_C
- добавить клаузу
- в список, возвращаемый предикатом getComponentIDInfo() добавить элемент вида
new([ИмяБазовогоИнтерфейсаКомпоненты]::componentID_C,Container)=Object:- !, Object = [ИмяБазовогоКлассаКомпоненты]::new(Container)
.
Обращения к pzl-Компоненте
Существуют три способа вызова создания экземпляра pzl-компоненты:
- путем вызова конструктора new(...)
- путем вызова предиката newByName(...)
- путем вызова предиката newByID(...)
Первый способ выглядит следующим образом:
... MyClassInstance =myClass::new(SomeObject), MyClassInstance:callNeededPredicate(…) ...
Это соответствует обычным правилам VIP.
Второй способ использует pzl-систему явно и выглядит так:
... MyClassObj=pzl::newByName(“MyClass”,...), MyClassInstance=tryConvert(iMyClass, MyClassObj), MyClassInstance:сallNeededPredicate(…),
Здесь iMyClass является интерфейсом класса myClass, а “MyClass” является строковым именем класса (alias) myClass.
Третий способ также явно использует pzl-систему и выглядит так:
... MyClassObj=pzl::newByID(str(“MyClass”),...), MyClassInstance=tryConvert(iMyClass, MyClassObj), MyClassInstance:сallNeededPredicate(…),
Здесь iMyClass является интерфейсом класса myClass, а str(“MyClass”) является строковым представлением идентификатора класса.
Обращение к другим классам и компонентам
Обращение к другим классам и компонентам из текущей компоненты ничем не отличается от обычного стиля обращений к классам, объектам классов и объектам компонент. Следует иметь в виду, что для обращения к компоненте в стиле
... ОбъектКомпоненты=классКомпоненты::new(SomeObject), ОбъектКомпоненты:предикатКомпонеты(Аргумент1,...), ...
компонента классКомпоненты должна быть представлена в проекте, из которого производится это обращение, своим классом-представителем.
Однако, для обращения к компоненте в стиле
... ОбъектКомпонентыObj=pzl::newByName("УсловноеИмяКомпоненты",Object), ОбъектКомпоненты=convert(интерфейсКомпоненты,ОбъектКомпонентыObj), ОбъектКомпоненты:предикатКомпонеты(Аргумент1,...), ...
или
... ОбъектКомпонентыObj=pzl::newByID(ИдентификаторКомпоненты,Object), ОбъектКомпоненты=convert(интерфейсКомпоненты,ОбъектКомпонентыObj), ОбъектКомпоненты:предикатКомпонеты(Аргумент1,...), ...
класс-представитель компоненты не требуется.
Завершение использования
По завершении использования объекта компоненты все указатели на нее должны быть удалены. Такое стандартное для VIP обращение с объектами в случае pzl-Компоненты также приводит к гибели ее объекта.
Отладка
Если pzl-компонента находится в главном (исполняемом) приложении, то отладка текста ее праграммы ничем не отличается от приемов отладки обычного класса системы Visual Prolog.
Если pzl-компонента находится в pzl-Контейнере, представляющем собой DLL, то процесс отладки должен начинаться с проекта этого контейнера (DLL). Впрочем, это типичный подход к отладке DLL, принятый в системе Visual Prolog.
Регистрация
Если какой-либо класс и pzl-компонента находятся в одной и той же сущности (.EXE или та же самая DLL), и при этом обращение производится в форме
... MyClassInstance =myClass::new(SomeObject), MyClassInstance:callNeededPredicate(…) ...
то регистрация pzl-Компоненты, к которой производится обращение, может не производиться.
Во всех остальных случаях компонента должна быть зарегистрирована
- либо в локальном файле пользователя
- либо в реестре LocalUser системы Windows (имя раздела HKEY_CURRENT_USER)
- либо в реестре LocalMashine системы Windows (имя раздела HKEY_LOCAL_MACHINE)
Примечание. Для регистрации компонент следует использовать специальные средства pzl-Технологии. Регистрация компонент вручную не рекомендуется.
При регистрации компоненты в реестре системы Windows используются следующие имена директорий windows-реестра (указаны в файле VpPuZzle/System/Packs/pzlDomains.i)
constants registryVPPuZzleAtGlobal_C = "vp_PuZzle". registryComponentsAtGlobal_C = "vp_PuZzle\\pzlComponents". registryVPPuZzleAtLocalUser_C = "Software\\vp_PuZzle". registryComponentsAtLocalUser_C = "Software\\vp_PuZzle\\pzlComponents". registryRunAble_C = "RunAble".
При этом для именования свойств компонент используются константы
registryRunAbleTrue_C="True". registryRunAbleFalse_C="False".
Получение информации о компоненте
Как уже упоминалось, следующие предикаты объявлены в интерфейсе pzlComponent и поддерживаются содержательно pzl-системой
- getContainerVersion() - возвращает информацию о версии контейнера, в котором данная компонента содержится
- getContainerName() - возвращает информацию об имени файла-контейнера, в котором содержится данная компонента
- getClassInfo(className,classVersion) - возвращает информации об имени и версии класса pzlComponent
Для того, чтобы внешние по отношению к данной компоненте средства могли бы получить информацию об идентификаторе, условном наименовании и метаинформации, рекомендуется помещать следующие клаузы в базовый класс pzl-компоненты:
caluses getComponentID()= componentID_C. getComponentAlias() = componentAlias_C. getComponentMetaInfo() = componentMetaInfo_C
Напоминаем, что объявления этих предикатов содержатся в интерфейсе pzlComponent.
Ограничения в несанкционированном использовании
Pzl-Компонента не содержит никаких средств для ограничения ее использования. Если программа получает доступ к контейнеру, в котором расположена pzl-Компонента, и программе известны интерфейсы для общения с компонентной, то эта pzl-Компонента оказывается доступной программе.
Вы, как автор pzl-Компоненты, можете предусмотреть дополнительные меры по ограничению прав использования pzl-Компоненты.
Например, Вы можете предусмотреть сеанс идентификации прав, в ходе которого в pzl-Компоненту должна быть передана информация, подтверждающая права на использование данной компоненты.
Если текст программы pzl-Компоненты недоступен широкому кругу пользователей, то такого рода защита от несанкционированного использования может оказаться достаточно эффективной.