Perl MooseX::Method::Signatures向所有方法注入自定义代码

Perl MooseX::Method::Signatures向所有方法注入自定义代码,perl,moose,moosex-types,Perl,Moose,Moosex Types,我正在尝试使用,在应用程序中,我需要在编译时而不是运行时在每个方法的开头插入自定义代码: 与此相反: use MooseX::Declare; method check ($value) { $return $value; } 我希望在编译时在每个方法的开头插入一段代码,如下所示: method check ($value) { my ($value) = $self->validate($value); $return $value; } method

我正在尝试使用,在应用程序中,我需要在编译时而不是运行时在每个方法的开头插入自定义代码:

与此相反:

use MooseX::Declare;

method check ($value) {
     $return $value;
}
我希望在编译时在每个方法的开头插入一段代码,如下所示:

method check ($value) {
     my ($value) = $self->validate($value);
     $return $value;
}
method check ($value) {
     say $me 
}
现在我要密码

我的($value)=$self->validate($value)

要在编译时而不是在运行时使用MooseX::Decare模块在包中所有方法的开头自动注入,我的意思是在编译前、编译后、编译前后不使用Moose方法修饰符

这需要修改这些模块,但我需要有人告诉我从哪里开始

我能够修改模块来做到这一点,并通过电子邮件向作者进行修改,但没有得到回复。我不能使用它的原因是,即使修改了它,因为它不支持类型检查和默认值,比如MooseX::Declare

以下模块的修改版本仅供参考,我使用如下:

使用方法::签名::简单(方法=>'Method,action',函数=> 'function',invocant=>'$this','inject'=>'my($me)=$this->me;')

现在在所有的方法中,我都得到了代码
my($me)=$this->me注入,我可以这样使用它:

method check ($value) {
     my ($value) = $self->validate($value);
     $return $value;
}
method check ($value) {
     say $me 
}
下面是修改后的方法::Signatures::Simple模块

package Method::Signatures::Simple;
{
  $Method::Signatures::Simple::VERSION = '1.07';
}

use warnings;
use strict;

=head1 NAME

Method::Signatures::Simple - Basic method declarations with signatures, without source filters

=head1 VERSION

version 1.07

=cut

use base 'Devel::Declare::MethodInstaller::Simple';

our $inject_code;

sub import {
    my $class = shift;
    my %opts  = @_;
    $opts{into} ||= caller;

    my $meth = delete $opts{name} || delete $opts{method};
    my $func = delete $opts{function};
    my $invocant = delete $opts{invocant} || '$self';
    $inject_code = delete $opts{inject};

    $inject_code .= ";" if ($inject_code && $inject_code !~ /\;$/);

    # if no options are provided at all, then we supply defaults
    unless (defined $meth || defined $func) {
        $meth = 'method';
        $func = 'func';
    }

    my @meth = split /\s*\,+\s*/, $meth;

    # we only install keywords that are requested
    foreach $meth (@meth) {
        if (defined $meth) {
            $class->install_methodhandler(
            name     => $meth,
            invocant => $invocant,
            %opts,
            );
        }
    }

    if (defined $func) {
        $class->install_methodhandler(
          name     => $func,
          %opts,
          invocant => undef,
        );
    }
}

sub strip_proto {
    my $self = shift;
    my ($proto) = $self->SUPER::strip_proto()
      or return '';
    # we strip comments and newlines here, and stash the number of newlines.
    # we will re-inject the newlines in strip_attrs(), because DD does not
    # like it when you inject them into the following code block. it does not
    # object to tacking on newlines to the code attribute spec though.
    # (see the call to inject_if_block() in DD::MethodInstaller::Simple->parser)
    $proto =~ s/\s*#.*$//mg;
    $self->{__nls} = $proto =~ s/[\r\n]//g;
    $proto;
}

sub strip_attrs {
    my $self = shift;
    my ($attrs) = $self->SUPER::strip_attrs();
    $attrs ||= '';
    $attrs .= $/ x $self->{__nls} if $self->{__nls};
    $attrs;
}

sub parse_proto {
    my $self = shift;
    my ($proto) = @_;
    $proto ||= '';
    $proto =~ s/\s*#.*$//mg;
    $proto =~ s/^\s+//mg;
    $proto =~ s/\s+$//mg;
    $proto =~ s/[\r\n]//g;
    my $invocant = $self->{invocant};

    $invocant = $1 if $proto =~ s{(\$\w+)\s*:\s*}{};

    my $inject = '';
    $inject .= "my ${invocant} = shift;" if $invocant;
    $inject .= "my ($proto) = \@_;"      if defined $proto and length $proto;
    $inject .= "$inject_code" if $inject_code;
    $inject .= '();'; # fix for empty method body

    return $inject;
}
并且提供了一种几乎与MooseX::Declare和MooseX::Method::Signatures兼容的语法,并通过traits设计为非常可扩展(甚至从内部!)。请注意以下几点:

警告:MooseX::Declare基于Devel::Declare,这是一个巨大的漏洞包,最初由mst实现,其目的是让perl核心开发人员非常不安,以至于他们在核心中实现了正确的关键字处理

[……]

如果您想在新代码中使用声明性语法,请为小猫们的爱准备一个最新的perl,并看看Moops

MooseX::Declare本身并不容易扩展。我知道

所以记住所有这些,并且因为我写了Moops,我将以它为例。这里我们定义了一个角色
Kavorka::TraitFor::Sub::ProvidesMe
,它将向一个方法中注入一点代码。然后,我们使用
doesprovideme
将该角色应用于方法

package main;
use Moops;

role Kavorka::TraitFor::Sub::ProvideMe
{
    around inject_prelude (@_)
    {
        my $prelude = $self->$next(@_);
        $prelude .= 'my ($me) = $self->me;();';
        return $prelude;
    }
}

class MyClass
{
    method me () { "tobyink" }

    method example () does ProvideMe
    {
        # This gets injected: my ($me) = $self->me;
        return $me;
    }
}

my $obj = MyClass->new;
say $obj->example;  ## says "tobyink"

问题是什么?简单地说,如何修改MooseX::Declare以向所有方法注入自定义代码?所以您是Perl巨人之一!。很高兴知道你是Moops的作者,但我看到它也在使用Moo,Moo是Moose的轻版本,如果与我已经使用过的Moose一起使用,会造成混乱。你的例子很好,但不是我想要的,我希望即使在你的Moops模块中也能有所改变,我相信你可以很容易地将它作为一个功能添加到Moops模块中。我也希望您使用Moose,或者将其作为在Moose内部使用Moose或Moo的一个选项。首先,与Moose的互操作性是Moo明确规定的设计目标。Moo类可以使用Moose角色,反之亦然。Moo子类可以扩展Moose超类,反之亦然。他们合作得很好。如果您遇到他们行为不好的情况,请将其报告为错误!(你可能会想到Mouse,它在与Moose的良好配合方面确实存在问题。)其次,Moops已经支持使用Moose构建类(或者如果你愿意,确实是Mouse)——你只需使用Moose{…}
编写
类Foo,你的类将使用Moose而不是Moo构建。容易的。