Модификаторы метода Perl Moose: вызывать «вокруг» до «до» и «после» - PullRequest
5 голосов
/ 09 ноября 2009

Я использую Moose, и мне нужно обернуть вызовы методов в моем проекте. Важно, чтобы мой код переноса был самым внешним модификатором. До сих пор я помещал мои модификаторы методов в роль лося, а затем применял эту роль в конце моего класса следующим образом:

use Moose::Util;
Moose::Util::apply_all_roles(__PACKAGE__->meta, ('App:Roles::CustomRole'));
__PACKAGE__->meta->make_immutable;

Это позволяет мне быть достаточно уверенным, что модификаторы моей роли определены в последнюю очередь, что дает мне правильное поведение для «до» и «после». («До» и «после» в роли называются самыми первыми и самыми последними.)

Изначально я думал, что этого будет достаточно, но теперь мне действительно нужно обернуть методы таким же образом, как "вокруг". Class :: MOP, на котором построен Moose, применяет модификаторы «вокруг» в первую очередь, поэтому они вызываются после «до» и до «после».

Для более подробной информации, вот текущий порядок вызовов моих модификаторов:

CUSTOM ROLE before
    before 2
       before 1
           CUSTOM ROLE around
               around
                   method
               around
           CUSTOM ROLE around
       after 1
    after 2
 CUSTOM ROLE AFTER

Мне действительно нужно что-то вроде этого:

CUSTOM ROLE before
    CUSTOM ROLE around
        before 2
           before 1
               around
                   method
               around
           after 1
        after 2
    CUSTOM ROLE around
 CUSTOM ROLE AFTER

Есть какие-нибудь идеи о том, как получить / вызвать мой модификатор "вокруг", куда я хочу? Я знаю, что мог бы сделать некоторый взлом таблицы символов (как Class :: MOP уже делает), но я бы действительно не хотел.

Ответы [ 2 ]

5 голосов
/ 09 ноября 2009

Самое простое решение состоит в том, чтобы ПОЛЬЗОВАТЕЛЬСКАЯ РОЛЬ определяла метод, который вызывает основной метод, а затем переносил его.

role MyRole { 
    required 'wrapped_method';
    method custom_role_base_wrapper { $self->wrapped_method(@_) }

    around custom_role_base_wrapper { ... }
    before custom_role_base_wrapper { ... }
}

Проблема, с которой вы сталкиваетесь, заключается в том, что вы пытаетесь заставить ПОЛЬЗОВАТЕЛЬСКУЮ РОЛЬ обернуть что-то другое , чем метод. Что не то, для чего он предназначен. Кроме написания подобной хакерской таблицы символов, как вы предлагали (возможно, вы могли бы поспорить с одним из людей Moose, чтобы он предоставил API в Class :: MOP, чтобы помочь в этом), единственное другое решение, которое я могу придумать, - это приведенное выше.

Если вам не нужен дополнительный кадр стека вызовов, который добавит custom_role_base_wrapper, вам следует взглянуть на Sub::Call::Tail Ювала или использовать goto для управления стеком вызовов.

3 голосов
/ 09 ноября 2009

Я довольно новичок в Moose, но зачем вы это делаете:

use Moose::Util;
Moose::Util::apply_all_roles(__PACKAGE__->meta, ('App:Roles::CustomRole'));

а не просто это?

with 'App:Roles::CustomRole';

Что касается вашего вопроса, то это немного хакерство, но не могли бы вы разделить ваш метод around на методы before и after и применить роль в конце определения вашего класса (чтобы он применялся в желаемый заказ)? Вы можете использовать приватные атрибуты для сохранения состояния между двумя методами, если это абсолютно необходимо.

...