Цитата:
Сообщение от
mazzy
это не единственный способ. и далеко не оптимальный.
как можно было бы реализовать,
если бы разработчикам поставили правильную задачу:
"создать фреймворк для добавления и изменения функционала, который будет доступен пользователям"
вместо нелепой задачи
"создать фреймворк для добавления классов"
============================
идея очень простая:
- не нужно никаких дополнительных классов-запускачей.
- [стандартный функционал] каждый класс запускается при помощи menuItem. в menuItem хранится объект, который должен быть запущен + метка + права + доп.строка параметров
- [стандартный функционал] menuItem запускает статический метод main
- [стандартный функционал] В main явно вызывается базовый класс с Args и добавленными в фреймворк стратегиями запуска
- [стандартный функционал] все контролируется штатными правами и штатными menuItem'ами.
- [стандартный функционал] окружение и инструменты (например, перекрестные ссылки) остаются в штатных режимах
- [стандартный функционал] класс можно вызывать из кода как при помощи menuFunction, так и вручную сформировав Args и запустив main.
- при правильных args, из кода можно запускать как main базового класса, так и main нужного класса
- construct базового класса вызывает фреймворк.
- каждый класс знает о себе, о своем базовом классе и о своей стратегии. ни одному классу, ни одному методу не нужно знаний обо всей иерархии.
- базовый класс можно сделать readOnly
- при желании, логику инстанцирования можно задавать при помощи параметра, а можно оставлять дефолтную
- при желании, логику запуска run можно задавать при помощи прараметра, а можно оставлять дефолтную
X++:
abstract class BaseClass_ReadOnly extends RunBaseBatch
{
protected static baseClass_ReadOnly construct(Args _args /*, SysExtensionInstantiationStrategy strategy = null*/)
{
var attr = new FormMenuItemFactoryAttribute(_args.menuItemType(), _args.menuItemName());
var obj = SysExtensionAppClassFactory::getClassFromSysAttribute(classStr(baseClass_ReadOnly), attr);
//TODO add initialization strategy
return obj;
}
public static void main(Args _args /*, SysExtensionInstantiationStrategy initStrategy = null */ )
{
baseClass_ReadOnly obj = BaseClass_ReadOnly::construct(_args /*, initStrategy */);
//TODO run strategy. Default is:
if( obj && obj.Prompt() )
{
obj.run();
}
}
}
вообще говоря, при правильно сформированных args, атрибут избыточен.
но для текущей версии фреймворка атрибут нужен.
X++:
[FormMenuItemFactoryAttribute(MenuItemType::Action, menuItemActionStr(myMenuItem))]
class MyClass extends BaseClass_ReadOnly
{
public void run()
{
//TODO something useful
}
public static void main(Args _args)
{
MyClass obj = BaseClass_ReadOnly::constuct(_args);
//TODO run strategy. Default is:
if( obj && obj.Prompt() )
{
obj.run();
}
}
}
menuItem указывает на нормальный объект
Код:
<?xml version="1.0" encoding="utf-8"?>
<AxMenuItemAction xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="Microsoft.Dynamics.AX.Metadata.V1">
<Name>myMenuItem</Name>
<Object>myClass</Object>
<ObjectType>Class</ObjectType>
</AxMenuItemAction>
=====================
кто-нибудь хочет проанализировать и рассказать про еще один фреймворк SysPlugin, который должен решать аналогичные задачи?
лучше в отдельной ветке.