Perl Moose 方法修饰符:调用“around”在“之前”之前以及“之后”

发布于 2024-08-10 08:40:11 字数 1123 浏览 2 评论 0原文

我正在使用 Moose,我需要在我的项目中包装方法调用。重要的是我的包装代码是最外层的修饰符。到目前为止,我所做的是将我的方法修饰符放入 Moose Role 中,然后在类末尾应用该角色,如下所示:

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

这使我能够合理地确定我的角色的修饰符是最后定义的,因此给了我“之前”和“之后”的正确行为。 (角色中的“before”和“after”被称为最先和最后一个。)

我最初认为这就足够了,但现在我确实需要以与“around”类似的方式包装方法。 Moose 所基于的 Class::MOP 首先应用“around”修饰符,因此它们在“before”之后和“after”之前被调用。

有关更多详细信息,这里是我的修饰符的当前调用顺序:

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

关于如何让我的“around”修饰符在我想要的地方应用/调用有什么想法吗?我知道我可以做一些符号表黑客(就像 Class::MOP 已经在做的那样),但我真的不想这样做。

I'm using Moose and I need to wrap method calls in my project. It's important that my wrapping code be the most outer modifier. What I've done so far is put my method modifiers in a Moose Role and then applied that role at the end of my class like this:

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

This allows me to be reasonably sure that my my role's modifiers are defined last, therefore giving me the correct behavior for "before" and "after." (The "before" and "after" in the role are called very first and very last.)

I originally thought this would be sufficient, but I now really need to wrap methods in a similar way with "around." Class::MOP, which Moose is built on, applies "around" modifiers very first, therefore they're called after "before" and before "after."

For more detail, here is the current calling order of my modifiers:

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

I really need something like this:

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

Any ideas on how to get my "around" modifier to be applied / called where I want it to? I know I could do some symbol table hacking (like Class::MOP is already doing) but I'd really rather not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

勿忘初心 2024-08-17 08:40:11

最简单的解决方案是让 CUSTOM ROLE 定义一个调用 main 方法的方法,然后包装它。

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

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

您遇到的问题是您试图让 CUSTOM ROLE 包含除方法之外的其他内容。这不是它的设计目的。除了像您建议的那样编写类似的符号表黑客技术(也许您可以说服一位 Moose 人在 Class::MOP 中公开 API 以帮助实现这一目标),我能想到的唯一其他解决方案就是上面的解决方案。

如果您不希望 custom_role_base_wrapper 添加额外的调用堆栈框架,您应该查看 Yuval 的 Sub::Call::Tail 或使用 goto 操作调用堆栈。

Simplest solution is to have CUSTOM ROLE define a method that calls the main method and then wrap that.

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

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

The problem you're having is that you're trying to have the CUSTOM ROLE around wrap something other than a method. Which is not what it is designed to do. Other than writing similar symbol table hackery like you've suggested (probably you could argue one of the Moose people into exposing an API in Class::MOP to help get there), the only other solution I can think of is the one above.

If you don't want the extra call stack frame that custom_role_base_wrapper will add, you should look at Yuval's Sub::Call::Tail or using goto to manipulate the call stack.

A君 2024-08-17 08:40:11

我对 Moose 相当陌生,但你为什么要这样做:

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

而不是简单地这样做?

with 'App:Roles::CustomRole';

关于您的问题,这有点像黑客,但是您可以将您的 around 方法拆分为 beforeafter 方法,并在你的类定义结束了(所以它按照你想要的顺序应用)?如果绝对必要,您可以使用私有属性来保存两个方法之间的状态。

I'm fairly new to Moose, but why do you do this:

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

rather than simply this?

with 'App:Roles::CustomRole';

Regarding your question, it's a bit of a hack, but could you split your around method into before and after methods and apply the role at the end of your class definition (so it is applied in your desired order)? You could use private attributes to save state between the two methods if absolutely necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文