|
|
|
|
#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 |
|
|
|
|
#2 |
|
Участник
|
Не делал. По виду идеи какой то изврат и не очень понятно зачем так.
XppCallStack по виду в IL разве будет корректно работать? С наступившим. Всех благ и здоровья вам +близким! |
|
|
|
|
#3 |
|
Участник
|
поясни, плиз, что там может некорректно работать?
__________________
Felix nihil admirari |
|
|
|
|
#4 |
|
Участник
|
|
|
|
|
| За это сообщение автора поблагодарили: gl00mie (5). | |
|
|
#5 |
|
Участник
|
нет, это не совсем то. моя проблема не в том, что я не могу перекрыть конечный метод - он как раз открыт всем ветрам, а в том, что не могу влезть во все вызывающие его 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 |
|
|
|
|
#6 |
|
Участник
|
Была старая дискуссия на яммере о использовании CallContext и все были посланы использовать disposable context из блога выше. Мы его (disposable) частенько используем, работает как часы.
|
|
|
|
| За это сообщение автора поблагодарили: Logger (3). | |
|
|
#7 |
|
Участник
|
Так его же надо инициализировать как раз там, где у меня полный приват. То есть это не решение проблемы.
Мне не нужен дополнительный аргумент - мне как раз нужно его заполнять
__________________
Felix nihil admirari |
|
|
|
|
#8 |
|
Участник
|
Обычно в таких случаях пишется "обертка" для стандартного класса, которая где-то выше по стеку вызовов инициализирует disposable context, а ниже по стеку отрабатывают стандартные private или какие угодно методы, вызывающие нужный код, и этот нужный код "видит", что его вызывают в определенном контексте, если так можно выразиться. Мне кажется, стоит все же посмотреть в сторону disposable context, а анализ стека вызовов, по-моему, - тупиковая ветвь развития, так вы заставите свой вызываемый код, как уже отмечалось, слишком много знать про вызывающий. Потом добавят какие-нить lambda-функции, которые в стеке вызовов будут выглядеть иначе, - и всё у вас сломается.
|
|
|
|
| За это сообщение автора поблагодарили: trud (1), wojzeh (3). | |
|
|
#9 |
|
Участник
|
__________________
Felix nihil admirari |
|
|
|
|
#10 |
|
Microsoft Dynamics
|
+1 за disposable из блога. Тоже использую по мере надобности не только в кустомерских модификациях, но и для кода написанного для МСа. Code review этот подход проходит.
|
|
|
|
|
#11 |
|
Участник
|
интересно, и что будет, если таких контекстов будет определено несколько, например, через те же расширения в методе insert? throw error('nesting is not supported')?
__________________
Felix nihil admirari |
|
|
|
|
#12 |
|
Microsoft Dynamics
|
Цитата:
позволяет иметь вложенные контексты. И тут уже в вашей воле реализовать необходимый функционал, типа, какой приоритет имеют поля в вашем контексте.
|
|
|
|
| За это сообщение автора поблагодарили: wojzeh (5). | |
|
|
#13 |
|
Участник
|
Парзинг стека приводит к тому, что вызываемый код начинает зависеть от вызывающего - если нужно будет второе место, из которого надо, определить то же поведение, придется в вызываемую функцию добавлять дополнительную логику.
И disposable context и парзинг стека не позволяет распознать ситуацию, когда чужой код вдруг стал вызывать ту же функцию на каком-то промежуточном уровне еще раз ожидая прежнего поведения. Еще не знаю как Dyn365FO, а в Ax2012, ЕМНИП, xppCallstack не работал из IL - и там пришлось бы пользоваться System.Environmen::get_Stacktrace() Последний раз редактировалось belugin; 07.01.2020 в 15:56. |
|
|
|
| За это сообщение автора поблагодарили: trud (3). | |
|
|
#14 |
|
Участник
|
как раз тот случай у меня, когда мне всё равно на другие случаи вызова моего кода, увы, праздник продолжался недолго.
столкнулся с другой проблемой: в стеке я вижу абстрактный класс, а не конкретный экземпляр дочернего класса...
__________________
Felix nihil admirari |
|
|
|
|
#15 |
|
Участник
|
Кстати про парсинг стека: кто-нибудь в курсе, нужно ли использовать Code Access Permission, или в D365FO все эти "new ExecutePermission().assert()" стали чем-то вроде рудиментов тазовых костей у китов? Если не ошибаюсь, эта фича использовала стек?
|
|
|
|
|
#16 |
|
Участник
|
Не нужно
|
|
|
|
| За это сообщение автора поблагодарили: Stitch_MS (3). | |
|
|
|