Показать сообщение отдельно
Старый 03.06.2017, 07:58   #92  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от 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, который должен решать аналогичные задачи?
лучше в отдельной ветке.
__________________
полезное на axForum, github, vk, coub.