03.01.2020, 23:06 | #1 |
Участник
|
call stack parsing as condition for logic
столкнулся тут с необходимостью переписывать кучу стандартных классов, которые через private методы вызывают один public табличный метод, который я легко могу перекрыть. но! в этом методе отсутствует нужный мне аргумент, чтобы определять контекст. и пришла мне в голову шальная мысль, а что если анализировать call stack внутри этого табличного метода, вместо переписывания кучи классов?
X++: ... container myCallStack; int i; str whatToWrite; myCallStack = xSession::xppCallStack(); for( i=1; i<=conlen(myCallStack); i++) { whatToWrite += conpeek(myCallStack, i); } if(callStackContainWhatINeed(whatToWrite)) { doMyWhim(); } ... с новым годом, кстати, всех, кто уже очнулся!
__________________
Felix nihil admirari |
|
03.01.2020, 23:26 | #2 |
Участник
|
Не делал. По виду идеи какой то изврат и не очень понятно зачем так.
XppCallStack по виду в IL разве будет корректно работать? С наступившим. Всех благ и здоровья вам +близким! |
|
04.01.2020, 01:33 | #3 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: gl00mie (5). |
04.01.2020, 17:26 | #4 |
Участник
|
нет, это не совсем то. моя проблема не в том, что я не могу перекрыть конечный метод - он как раз открыт всем ветрам, а в том, что не могу влезть во все вызывающие его private методы.
но считай, что "иронию судьбы" ты всё-таки посмотрел, потому что я опирался на твой собственный пример из этого топика X++: boolean isApplicableTo(AnyType _value) { #localMacro.runningUnitTestsClient '(C)\\Classes\\SysTestSuite\\run' #endmacro #localMacro.runningUnitTestsServer '(s)\\Classes\\SysTestSuite\\run' #endmacro container callStack; if (_value && typeOf(_value) == Types::Class) { callStack = xSession::xppCallStack(); if (conFind(callStack, #runningUnitTestsClient) || conFind(callStack, #runningUnitTestsServer)) { return AOTResourceTemplateProviderTestHelper_RU::applicable(); } } return false; }
__________________
Felix nihil admirari |
|
04.01.2020, 17:27 | #5 |
Участник
|
поясни, плиз, что там может некорректно работать?
__________________
Felix nihil admirari |
|
04.01.2020, 22:06 | #6 |
Участник
|
Была старая дискуссия на яммере о использовании CallContext и все были посланы использовать disposable context из блога выше. Мы его (disposable) частенько используем, работает как часы.
|
|
|
За это сообщение автора поблагодарили: Logger (3). |
04.01.2020, 23:11 | #7 |
Участник
|
Так его же надо инициализировать как раз там, где у меня полный приват. То есть это не решение проблемы.
Мне не нужен дополнительный аргумент - мне как раз нужно его заполнять
__________________
Felix nihil admirari |
|
04.01.2020, 23:18 | #8 |
Участник
|
__________________
Felix nihil admirari |
|
05.01.2020, 01:40 | #9 |
Microsoft Dynamics
|
+1 за disposable из блога. Тоже использую по мере надобности не только в кустомерских модификациях, но и для кода написанного для МСа. Code review этот подход проходит.
|
|
05.01.2020, 03:15 | #10 |
Участник
|
интересно, и что будет, если таких контекстов будет определено несколько, например, через те же расширения в методе insert? throw error('nesting is not supported')?
__________________
Felix nihil admirari |
|
05.01.2020, 03:26 | #11 |
Microsoft Dynamics
|
Если речь идет о разных контекстах, то ничего такого не будет. Код, который находится ниже по стеку вызовов, знает только о своем контексте. Если об одном и том же контексте, то небольшая доработка (MyContext parentContext позволяет иметь вложенные контексты. И тут уже в вашей воле реализовать необходимый функционал, типа, какой приоритет имеют поля в вашем контексте.
|
|
|
За это сообщение автора поблагодарили: wojzeh (5). |
07.01.2020, 15:53 | #12 |
Участник
|
Парзинг стека приводит к тому, что вызываемый код начинает зависеть от вызывающего - если нужно будет второе место, из которого надо, определить то же поведение, придется в вызываемую функцию добавлять дополнительную логику.
И disposable context и парзинг стека не позволяет распознать ситуацию, когда чужой код вдруг стал вызывать ту же функцию на каком-то промежуточном уровне еще раз ожидая прежнего поведения. Еще не знаю как Dyn365FO, а в Ax2012, ЕМНИП, xppCallstack не работал из IL - и там пришлось бы пользоваться System.Environmen::get_Stacktrace() Последний раз редактировалось belugin; 07.01.2020 в 15:56. |
|
|
За это сообщение автора поблагодарили: trud (3). |
07.01.2020, 18:49 | #13 |
Участник
|
как раз тот случай у меня, когда мне всё равно на другие случаи вызова моего кода, увы, праздник продолжался недолго.
столкнулся с другой проблемой: в стеке я вижу абстрактный класс, а не конкретный экземпляр дочернего класса...
__________________
Felix nihil admirari |
|
10.01.2020, 03:55 | #14 |
Участник
|
Обычно в таких случаях пишется "обертка" для стандартного класса, которая где-то выше по стеку вызовов инициализирует disposable context, а ниже по стеку отрабатывают стандартные private или какие угодно методы, вызывающие нужный код, и этот нужный код "видит", что его вызывают в определенном контексте, если так можно выразиться. Мне кажется, стоит все же посмотреть в сторону disposable context, а анализ стека вызовов, по-моему, - тупиковая ветвь развития, так вы заставите свой вызываемый код, как уже отмечалось, слишком много знать про вызывающий. Потом добавят какие-нить lambda-функции, которые в стеке вызовов будут выглядеть иначе, - и всё у вас сломается.
|
|
|
За это сообщение автора поблагодарили: trud (1), wojzeh (3). |
15.01.2020, 23:35 | #15 |
Участник
|
Кстати про парсинг стека: кто-нибудь в курсе, нужно ли использовать Code Access Permission, или в D365FO все эти "new ExecutePermission().assert()" стали чем-то вроде рудиментов тазовых костей у китов? Если не ошибаюсь, эта фича использовала стек?
|
|
16.01.2020, 06:46 | #16 |
Участник
|
Не нужно
|
|
|
За это сообщение автора поблагодарили: Stitch_MS (3). |
|
|