Показать сообщение отдельно
Старый 26.01.2022, 16:52   #439  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
В D365FO семейство классов RAssetProposal очень "занятно" распаковывает параметры в unpack(), из-за чего не так просто добавлять в это семейство новые параметры для сохранения в pack()/unpack().
Коллега недавно наткнулся на проблему, пытаясь применить к этому семейству рекомендации по расширению наследников RunBase. В рекомендациях говорится, что в pack() вашего класса-расширения нужно написать примерено так:
X++:
public container pack()
{
    container packedClass = next pack();
    return SysPackExtensions::appendExtension(packedClass, classStr(MySysUserLogCleanup_Extension), this.myPack());
}
При этом - внимание! - в конец общего контейнера допишется еще один элемент-контейнер с параметрами вашего расширения. Если расширений несколько, то, вероятно, допишется не один элемент, а несколько. В unpack() же класса-расширения вам надо написать примерно вот так:
X++:
public boolean unpack(container _packedClass)
{
    boolean result = next unpack(_packedClass);
    if (result)
    {
        container myState = SysPackExtensions::findExtension(_packedClass, classStr(MySysUserLogCleanup_Extension));
        result = this.myUnpack(myState); //Also unpack the extension
    }
    return result;
}
Но в случае RAssetProposal следование официальной инструкции приводит к ошибке времени выполнения в расширяемом классе: невозможно инициализировать queryRun из контейнера.
Вот как бы вы работали с queryRun в pack/unpack? Обычно это выглядит так:
X++:
public container pack()
{
    return [#CurrentVersion, #CurrentList, queryRun.pack()];
}
X++:
public boolean unpack(container _packedClass)
{
    Version version = RunBase::getVersion(_packedClass);
    boolean ret = true;

    switch (version)
    {
        case #CurrentVersion :
            container packedQuery;
            [version, #CurrentList, packedQuery] = _packedClass;
            if (SysQuery::isPackedOk(packedQuery))
            // ...
Обратите внимание, что конструкция вида
X++:
[version, #CurrentList, packedQuery] = _packedClass;
симметрична конструкции
X++:
return [#CurrentVersion, #CurrentList, queryRun.pack()];
она позволяет безболезненно отбросить все лишние элементы в конце контейнера _packedClass и взять своё строго с тех позиций, какие получились в вашем pack().
Но локализаторы же хитрее всех, поэтому они считают, что их запакованный queryRun всегда идет последним, и пишут вот что:
X++:
public boolean unpack(container packedClass)
{
    Integer     version = conPeek(packedClass,1);
    container   packedQuery = conPeek(packedClass, conLen(packedClass));
Поскольку наш контейнер стал длиннее за счет параметров класса-расширения, то вместо запакованного queryRun локализаторы, разумеется, получают левый контейнер и валятся на нем в ошибку времени выполнения.
За это сообщение автора поблагодарили: ax_mct (5), S.Kuskov (5), dech (10), Pandasama (2).