AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 07.11.2018, 15:54   #1  
malex is offline
malex
Участник
 
164 / 19 (1) ++
Регистрация: 10.08.2004
Адрес: Тверь, Москва
? D365FO: Inheritance + Extensions + RealTime
Есть 8.0 PU15. Переношу overlaid-решение на extensions.

В классе InventMovement был кастом-метод, который был перекрыт в наследниках (InventMov_Purch)
Я создал extensions к этим методам и ожидаю, что в real-time вызовется нужный extension:
X++:
[ExtensionOf(classStr(InventMovement))]
final class InventMovementAQM_Extension
{
    boolean AQMmustUpdateBatchInfo()
    {
        return false;
    }
}

[ExtensionOf(classStr(InventMov_Purch))]
final class InventMov_PurchAQM_Extension
{
    boolean AQMmustUpdateBatchInfo()
    {
        return true;
    }

}
Вызов (COC):
X++:
[ExtensionOf(tableStr(InventBatch))]
final class InventBatchAQM_Extension
{
    public void initFromInventMovement(InventMovement _inventMovement, InventTrans _inventTrans)
    {
        next initFromInventMovement(_inventMovement, _inventTrans);

        if (_inventMovement.AQMmustUpdateBatchInfo())
        {
            // blablabla
        }
    }
В realtime передаю в _inventMovement InventMov_Purch и ожидаю, что вызовется AQMmustUpdateBatchInfo() у экстеншена InventMov_PurchAQM_Extension. Однако вызов происходит у InventMovementAQM_Extension (параметр объявлен как InventMovement)

Если сделать явное преобразование
X++:
InventMov_Purch invMov;
        invMov = _inventMovement;
        if (invMov.AQMmustUpdateBatchInfo())
        {
        }
То будет вызов как я ожидаю.

Как Вы считаете - это баг? В 8.1\8.1.1\8.1.2 система ведет себя также?
Старый 07.11.2018, 17:11   #2  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Wrapping a base method in an extension of a derived class
The following example shows how to wrap a base method in an extension of a derived class. For this example, the following class hierarchy is used.


X++:
class A
{
    public void salute(str message)
    {   
        info(message);
    }
}

class B extends A {}
class C extends A {}
Therefore, there is one base class, A. Two classes, B and C, are derived from A. We will augment or create an extension class of one of the derived classes (in this case, B), as shown here.


X++:
[ExtensionOf(classStr(B))]
final class B_Extension
{
    public void salute(str message)
    {
        next salute(message);
        info("B extension");
    }
}
Although the B_Extension class is an extension of B, and B doesn't have a method definition for the salute method, you can wrap the salute method that is defined in the base class, A. Therefore, only instances of the B class will include the wrapping of the salute method. Instances of the A and C classes will never call the wrapper method that is defined in the extension of the B class.

This behavior becomes clearer if we implement a method that uses these three classes.

X++:
class ProgramTest 
{
    public static void main(Args args)
    {
        var a = new A();
        var b = new B();
        var c = new C();

        a.salute("Hi");
        b.salute("Hi");
        c.salute("Hi");
    }
}
For calls to a.salute(“Hi”) and c.salute(“Hi”), the Infolog shows only the message “Hi.” However, when b.salute(“Hi”) is called, the Infolog shows “Hi” followed by “B extension.”

By using this mechanism, you can wrap the original method only for specific derived classes.

https://docs.microsoft.com/en-us/dyn...d-wrapping-coc
__________________
Felix nihil admirari

Последний раз редактировалось wojzeh; 07.11.2018 в 17:13.
Старый 07.11.2018, 18:30   #3  
malex is offline
malex
Участник
 
164 / 19 (1) ++
Регистрация: 10.08.2004
Адрес: Тверь, Москва
?
Цитата:
Сообщение от wojzeh Посмотреть сообщение
Wrapping a base method in an extension of a derived class
The following example shows how to wrap a base method in an extension of a derived class. For this example, the following class hierarchy is used:
Здравствуйте, wojzeh. Спасибо за ответ. У меня немного другая ситуация: у меня нет COC, но есть extension для базового класса и extension для наследника. Если переменная объявлена как базовый класс, но в realTime инициализируется как наследник, то extension все равно вызывается для базового класса.
(Thank you for your answer. I have the different case: I havn't COC. I have extensions for parent class and for a child. Both extensions has the same method. A class variable declared as a parent class, but initialized as a child. The system invokes extension for the parent class)
X++:
class A
{
}
class B extends A
{
}
[ExtensionOf(classStr(A))]
final class A_Extension
{
    public void salute()
    {
        info("A extension");
    }

}
[ExtensionOf(classStr(B))]
final class B_Extension
{
    public void salute()
    {
        info("B extension");
    }

}
X++:
class Test01
{        
    public static void main(Args _args)
    {    
        A a;

        a = new B(); 

        a.salute();
    }

}
В результате получим "A extension".
За это сообщение автора поблагодарили: Logger (5), Pokersky09 (2).
Старый 07.11.2018, 21:50   #4  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
технически у тебя два разных класса: исходный и его расширения. очевидно невозможно перекрывать методы расширений (они ж final) ни в классах наследниках, ни в их, наследниках, расширениях. поэтому, строго говоря, это вообще два разных метода у тебя, несмотря на то, что имена у них одинаковы.

если бы расширение класса-наследника "видело" все добавленные во всех расширениях методы класса-родителя, то потребовалось бы вызывать next. и наоборот, если бы расширенные методы класса-родителя трактовались как "родные", они были бы доступны к перекрытию, но ты не можешь вызвать super во втором методе.

так что IS и AS твои друзья тут
__________________
Felix nihil admirari
За это сообщение автора поблагодарили: trud (2), malex (1), ax_mct (3).
Старый 08.11.2018, 09:44   #5  
malex is offline
malex
Участник
 
164 / 19 (1) ++
Регистрация: 10.08.2004
Адрес: Тверь, Москва
Post
Цитата:
Сообщение от wojzeh Посмотреть сообщение
так что IS и AS твои друзья тут
Я так и поступил, но надеялся что это был workaround. Придется почти весь код из наследников переносить в родительский классы с кучей кейсов.

PS: Я все таки думал что на уровне своих методов в экстеншенах будет наследование. А то получается мы у себя в МС будем использовать наследование и override, а вы со своими ISV решениями мучайтесь как хотите и плевать что архитектура внутри у вас будет не очень и с кучей дублирования кода.

Последний раз редактировалось malex; 08.11.2018 в 09:46.
Старый 08.11.2018, 10:51   #6  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,907 / 5717 (196) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Цитата:
Сообщение от malex Посмотреть сообщение
Я так и поступил, но надеялся что это был workaround. Придется почти весь код из наследников переносить в родительский классы с кучей кейсов.

PS: Я все таки думал что на уровне своих методов в экстеншенах будет наследование. А то получается мы у себя в МС будем использовать наследование и override, а вы со своими ISV решениями мучайтесь как хотите и плевать что архитектура внутри у вас будет не очень и с кучей дублирования кода.
А не думали над таким подходом:
1. Определить свои классы как наследники inventMov_purch, inventMov_Sales и тп
2. Переопределить с помощью CoC метод inventMovement::constructNoThrow(), так чтобы он возвращал экземпляры своих классов, вместо стандартных ?
Старый 08.11.2018, 12:14   #7  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Может я глупость скажу, но в исходном примере final class InventMovementAQM_Extension то есть эктеншены это два не связанных между собою типа и добавляют два несвязанных между собой метода. Вы пробовали унаследовать один от другого?
Старый 12.11.2018, 23:31   #8  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Макс, это не глупость, а именно то же, что уже сказал я. Раз нас уже двое, то мы не можем ошибаться!
__________________
Felix nihil admirari
Старый 13.11.2018, 04:14   #9  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Тут кстати есть где сконфьюзиться
Цитата:
the classes that inherit from a class that has extensions inherit the methods that are defined in the extension classes.
https://docs.microsoft.com/en-us/dyn...ass-extensions

Концепция эффективного класса. Причем эта "сборка" еще зависит от включенных моделей. Как я понимаю extension это не про "extend", а про "add".

The effective class concept


Старый 13.11.2018, 04:19   #10  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Важно что это на самом деле class augmentation (приращение) просто они для красного словца используют class extension
Цитата:
The functionality for class extension, or class augmentation,
Старый 13.11.2018, 11:33   #11  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от wojzeh Посмотреть сообщение
Макс, это не глупость, а именно то же, что уже сказал я. Раз нас уже двое, то мы не можем ошибаться!
Я имел ввиду, что, может, достаточно сделать их наследниками (но, соответственно, получается что от фреймворка требуется соблюдения правила что подкласс вытесняет суперкласс из экстешненов, а соблюдается ли оно, я не знаю)
Старый 19.11.2018, 21:15   #12  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
как это ты их сделаешь наследниками?
__________________
Felix nihil admirari
Старый 20.11.2018, 15:08   #13  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от wojzeh Посмотреть сообщение
как это ты их сделаешь наследниками?
Вернее, одного вылечить от бездетности, а второго сделать наследником.

X++:
// remove "final"
class InventMovementAQM_Extension
...

// add "extends"
final class InventMov_PurchAQM_Extension extends InventMovementAQM_Extension
...

Последний раз редактировалось belugin; 20.11.2018 в 15:09. Причина: Запятые - это важно!
Старый 21.11.2018, 00:52   #14  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
ух ты! а вот у этого, второго, который не стрелял, у него на шапке звезда горит и написано [ExtensionOf(?)] ?
__________________
Felix nihil admirari
Старый 21.11.2018, 09:45   #15  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Ну да. Сам не пробовал, но интересно, что получится.
Старый 21.11.2018, 17:07   #16  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
ничего не получится!

любой extension - это final, а final - это кастрат, у которого наследников в принципе не бывает.

так что твоя идея по определению неосуществима. воспринимай extension как крюк вместо руки у пирата. сын пирата не родится с крюком никогда. сыну пирата, конечно, тоже можно отрубить руку и приделать крюк, но это будут два разных крюка. пик рилейтед.

Нажмите на изображение для увеличения
Название: крюк.png
Просмотров: 280
Размер:	296.8 Кб
ID:	12146
__________________
Felix nihil admirari
Старый 10.10.2023, 11:37   #17  
kair84 is offline
kair84
Участник
 
47 / 58 (2) ++++
Регистрация: 15.04.2010
Адрес: Belarus
Решение есть
Прошу прощение за Офтоп, У меня недавно возникла необходимость сделать подобное, и все получилось, не так красиво как я бы хотел но все же:

X++:
class A
{
}
class B extends A
{
}
[ExtensionOf(classStr(A))]
final class A_Extension
{
    public void salute()
    {
        switch (true)
        {
            case this is B:    
                B b = this ;
                b.salute();
            default :
                info("A extension");
        }        
    }
}
[ExtensionOf(classStr(B))]
final class B_Extension
{
    public void salute()
    {
        info("B extension");
    }

}
В идеале хотелось бы обойтись без упоминания конкретного наследника, через DictClass или что то подобное, но пока только так получилось.
Старый 10.10.2023, 11:43   #18  
kair84 is offline
kair84
Участник
 
47 / 58 (2) ++++
Регистрация: 15.04.2010
Адрес: Belarus
Нет, это не Офтоп.... как то по другому называется
Старый 11.10.2023, 00:43   #19  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,308 / 3540 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от kair84 Посмотреть сообщение
Прошу прощение за Офтоп, У меня недавно возникла необходимость сделать подобное, и все получилось, не так красиво как я бы хотел но все же:
Знаю. Добивался этого же. Это по сути эмуляция наследования.
Какие в этом случае всплывают проблемы:
1. (Основная). Очевидно, что это работает только для новых методов. Т.е. нельзя в классе А сделать расширение стандартного метода (с использованием метода next), потому что next не позволяет себя вызывать "по условию". Точнее сделать-то можно, вот только когда сделаешь - получается, что можно было сделать проще без этих "выкрутасов".
2. (Организационная). Каждый разработчик должен будет этот "стиль" поддерживать при добавлении нового метода.
3. (Организационная). При наличии нескольких расширений одного класса - они формально могут применяться в любой последовательности. Следовательно код можно писать только такой, который не будет зависеть от последовательности вызова разных расширений.

Т.е. да, чисто академически - так можно написать. Но реально претворить это в жизнь.... весьма сложно, а главное - относительно без особой выгоды.
__________________
Возможно сделать все. Вопрос времени
Старый 11.10.2023, 11:17   #20  
ТРЕНЕР is offline
ТРЕНЕР
Участник
Аватар для ТРЕНЕР
 
599 / 50 (3) ++++
Регистрация: 11.06.2003
Адрес: Москва
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
При наличии нескольких расширений одного класса - они формально могут применяться в любой последовательности.
Да, сталкивался с этим. Один и тот же функционал работал в разные моменты по-разному. Оказалось, что именно из-за разной произвольной последовательности работы нескольких расширений.
Теги
chain of command, d365fo

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
erconsult: Copy-paste with keyboard script 2: from Excel to D365FO Blog bot DAX Blogs 0 03.08.2018 11:12
daxmusings: The Overall Concept of Extensions in AX 7 Blog bot DAX Blogs 0 14.09.2017 13:11
sertandev: AX7 Extensibility Overview – Part 2 : Code extensions Blog bot DAX Blogs 0 28.08.2017 19:11
daxmusings: The Overall Concept of Extensions in AX 7 Blog bot DAX Blogs 0 04.10.2016 12:11
goshoom: Class extensions Blog bot DAX Blogs 0 18.07.2016 17:11
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 06:23.