2009-11-09 94 views
5

我正在使用Moose,我需要在我的項目中包裝方法調用。重要的是我的包裝代碼是最外面的修飾符。Perl Moose方法修飾符:在'之前'和'之後'調用'around'

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

這使我有理由相信我的我的角色的修飾符:我到目前爲止所做的就是把我的方法修飾符在穆斯的角色,然後在我的課像這樣結束時應用該角色最後定義,因此給我「之前」和「之後」的正確行爲。 (角色中的「之前」和「之後」被稱爲非常先和非常後)。

我原本以爲這樣就足夠了,但我現在真的需要用類似的方法來包裝方法。 Class :: MOP是Moose的基礎,它首先應用「around」修飾符,因此它們在「之前」之前和之後「之後」被調用。

更多的細節,這裏是我的修飾符的當前調用順序:

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已經在做的那樣),但是我真的不想。

+1

我同意以下的Ether的問題,爲什麼你使用'Moose :: Util :: apply_all_roles'而不是'with'? – perigrin 2009-11-09 20:40:12

+0

我希望我的角色中的「之前」和「之後」修飾符與其他可能存在於該類中的修飾符相比,首先運行或最後運行。稍後應用角色定義修飾符,然後修飾符會先運行(用於之前)和最後(用於之後)。 – 2009-11-09 21:57:39

+0

@perigrin我終於明白了你和Ether的問題。我不需要像我想象的那樣將apply_all_roles應用於角色。對於Moose,我還是一個新手,並且想到了需要「手動」應用這個角色的想法。我真正需要做的只是在文件末尾(在其他修飾符之後)使用「with」,而不是開頭。 – 2009-11-10 15:40:22

回答

4

最簡單的解決方案是讓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 { ... } 
} 

您遇到的問題是,你想擁有的繞到東西其他不是方法的自定義角色。這不是它設計的目的。除了像你所建議的那樣編寫類似的符號表hackery(可能你可能會爭論Moose中的一個人將Class :: MOP中的API暴露出來以幫助實現此目標),但我能想到的唯一的其他解決方案就是上面的那個。

如果你不想要custom_role_base_wrapper將添加額外的調用堆棧幀,你應該看看Yuval的Sub::Call::Tail或使用goto來操縱調用堆棧。

+0

我結束了自定義包裝的想法。它給了我需要的靈活性,謝謝。 – 2009-11-24 16:23:42

3

我是相當新的駝鹿,但是你爲什麼這樣做:

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

而不是簡單呢?

with 'App:Roles::CustomRole'; 

關於你的問題,這是一個黑客攻擊的一位,但你可以分割你的around方法爲beforeafter方法和類定義的末尾應用中的作用(故在您需要的順序應用)?如果絕對必要,您可以使用私有屬性來保存兩種方法之間的狀態。

+1

問題是''之前'和'之後'都不能讓你(乾淨地)以'around'的方式改變返回語義。如果這些語義很重要,那就搞定了。如果他們不是,爲什麼你用'around'開始? – perigrin 2009-11-09 20:38:52

+0

我手動應用它的原因是修改器按照它們定義的順序添加(然後運行)。一般來說,你不關心訂單修飾符的運行。但是,就我而言,我希望我的角色的修飾成爲之前和之後的第一個。 如果使用「with」語法來應用角色,則首先定義其修飾符,以便它們將作爲「之前」和「之後」的最內層運行。通過在最後手動應用角色,它們是最後定義的,因此在我希望它們運行時運行。 – 2009-11-09 21:51:36

+0

@Matt:這確實似乎是Moose的一個缺點。也許'after'語義應該允許改變返回值爲'around',或者'before','around'和'after'方法的順序應該被修改,所以它們都是相對於彼此的LIFO,而是而不僅僅是對自己(如果這是有道理的)。 – Ether 2009-11-10 00:34:50

相關問題