2009-11-09 8 views
5

Ich benutze Moose und ich muss Methodenaufrufe in meinem Projekt umhüllen. Es ist wichtig, dass mein Umbruchcode der äußerste Modifikator ist. Was ich bisher getan ist meine Methode Modifikatoren in einem Elch Role setzen und angewandt, dann wird diese Rolle am Ende meiner Klasse wie folgt:Perl Moose Method Modifiers: Call 'herum' vor 'vor' und 'nach'

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

Das ist mir einigermaßen sicher sein kann, dass meine meine Rolle Modifikatoren Definiert als letztes und gibt mir das richtige Verhalten für "vorher" und "danach". (Das "Vorher" und das "Nachher" in der Rolle werden zuerst und zuletzt genannt.)

Ursprünglich dachte ich, das wäre ausreichend, aber jetzt muss ich die Methoden in ähnlicher Weise mit "around" umhüllen. Class :: MOP, auf dem Moose basiert, wendet "around" -Modifikatoren zuerst an, daher werden sie nach "vorher" und vor "nachher" benannt.

Für weitere Einzelheiten hier ist die aktuelle Berufung Reihenfolge meiner Modifikatoren:

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

ich wirklich so etwas wie dieses brauchen:

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

Alle Ideen, wie meine „um“ Modifikator zu erhalten Wo soll ich es anwenden? Ich weiß, dass ich einige Symboltabellen hacken könnte (wie Class :: MOP macht das schon), aber ich würde es wirklich nicht tun.

+1

Ich stimme Ether Frage unten, warum verwenden Sie 'Moose :: Util :: apply_all_roles' anstatt 'mit'? – perigrin

+0

Ich wollte, dass die Modifizierer 'before' und 'after' in meiner Rolle ganz im Vergleich zu anderen Modifiern, die bereits in der Klasse existieren, zuerst oder zuletzt ausgeführt werden. Wenn Sie die Rolle manuell zuweisen, werden die Modifikatoren später definiert und dann werden die Modifikatoren zuerst (für vorher) und zuletzt (für nach) ausgeführt. –

+0

@perigrin Ich habe endlich deine und Ethers Frage verstanden. Ich muss die Rolle nicht mit apply_all_roles anwenden, wie ich dachte.Ich bin immer noch neu bei Moose und habe mich auf die Idee gefasst, die Rolle "manuell" anwenden zu müssen. Alles, was ich wirklich tun musste, war, es mit "mit" am Ende der Datei (nach den anderen Modifikatoren) und nicht am Anfang anzuwenden. –

Antwort

4

Die einfachste Lösung ist CUSTOM ROLE zu definieren eine Methode, die die Hauptmethode aufruft und dann umschließt.

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

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

Das Problem, das Sie ist, dass Sie versuchen, die benutzerdefinierte Rolle um wickeln etwas andere als eine Methode zu haben. Was ist es nicht, was es zu tun ist. Anders als das Schreiben ähnlicher Symboltabellen-Hacker, wie du es vorgeschlagen hast (wahrscheinlich könntest du einen der Elch-Leute dazu bringen, eine API in Class :: MOP herauszubringen, um dorthin zu gelangen), die einzige andere Lösung, die ich mir vorstellen kann, ist die obige.

Wenn Sie nicht den zusätzlichen Anruf Stapelrahmen möchten, dass custom_role_base_wrapper hinzufügen, sollten Sie bei Yuval die aussehen Sub::Call::Tail oder mit goto den Call-Stack zu manipulieren.

+0

Ich endete mit der benutzerdefinierten Wrapper-Idee. Es gab mir die Flexibilität, die ich brauchte, danke. –

3

Ich bin ziemlich neu in Moose, aber warum tun Sie dies:

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

anstatt einfach das?

with 'App:Roles::CustomRole'; 

Zu Ihrer Frage, es ist ein bisschen wie ein Hack, aber könnten Sie teilen Sie Ihre around Methode in before und after Methoden und wenden Sie die Rolle am Ende der Klassendefinition (so ist es in der gewünschten Reihenfolge angewendet) Sie können private Attribute verwenden, um den Status zwischen den beiden Methoden zu speichern, wenn dies unbedingt erforderlich ist.

+1

Das Problem ist, dass weder "vor" noch "nach" Sie (sauber) die Rückkehrsemantik so verändern können, wie es "um" wird. Wenn diese Semantik wichtig ist, bist du verrückt. Wenn das nicht der Fall ist, warum benutzt du dann "herum"? – perigrin

+0

Der Grund, warum ich es manuell anwende, ist, dass die Modifikatoren in der Reihenfolge, in der sie definiert sind, hinzugefügt (und dann ausgeführt) werden. Im Allgemeinen ist es egal, dass die Order Modifier ausgeführt werden. Aber ich wollte, dass die Modifikatoren meiner Rolle die allerersten sind, vor und nachher. Wenn Sie die "mit" -Syntax verwenden, um die Rollen anzuwenden, werden die Modifizierer zuerst definiert und so werden sie als innerste "Vorher" und "Nachher" ausgeführt. Durch die manuelle Anwendung der Rolle am Ende werden sie zuletzt definiert und werden daher ausgeführt, wenn ich sie haben möchte. –

+0

@Matt: Das scheint tatsächlich ein Manko von Moose zu sein. Vielleicht sollte die 'after'-Semantik erlauben, den Rückgabewert zu ändern, wie 'ringsum', oder die Reihenfolge der' Vorher'-, 'Um'- und 'Nachher'-Methoden sollte so modifiziert werden, dass sie alle LIFO sind, relativ zueinander als nur sich selbst (wenn das Sinn macht). – Ether

Verwandte Themen