首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl::Method::Signatures向所有方法注入自定义代码

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

Stack Overflow用户
提问于 2014-05-22 19:19:36
回答 1查看 236关注 0票数 2

我试图在应用程序中使用MooseX::方法::签名MooseX::声明,我需要在编译时(而不是在运行时)在每个方法的开头注入自定义代码:

而不是这样:

代码语言:javascript
复制
use MooseX::Declare;

method check ($value) {
     $return $value;
}

我希望在编译时在每个方法的开头注入一个代码,如下所示:

代码语言:javascript
复制
method check ($value) {
     my ($value) = $self->validate($value);
     $return $value;
}

现在我要密码

my ($value) =$self->$value($value);

使用MooseX::Decalre模块在编译时(而不是在运行时)在包中的所有方法开始时自动注入,我的意思是在编译之前、之后、前后等都不使用Moose方法修饰符。

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

我能够修改模块方法::签名::简单来做到这一点,并给作者发了电子邮件要求修改,但没有得到回复。即使经过修改,我也不能使用它,因为它不支持类型检查和默认设置,比如MooseX::Declare。

下面的模块方法::签名::简单的修改版本供参考,我使用它如下:

使用方法::签名::Simple(方法=> 'method,action',function‘=> 'function',invocant=’$this‘,’inject‘=’my ($me) = $this->me;');

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

代码语言:javascript
复制
method check ($value) {
     say $me 
}

以下是修改过的方法::签名::Simple模块。

代码语言:javascript
复制
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;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-22 22:17:11

驼鸟卡沃卡提供了一种与MooseX::Declare和MooseX::方法::签名几乎兼容的语法,并且设计得非常可扩展(甚至从内部!)通过特征。我将提请您注意以下MooseX文件一节::声明

警告:MooseX:是基于Devel::,最初是由实现的一个巨大的裂缝,其目的在于让核心开发人员因为其存在而感到不安,以至于他们在内核中实现了正确的关键字处理。 ..。 如果您想在新代码中使用声明式语法,请为了小猫的喜爱,给自己买一个最新的perl,然后看看Moops。

MooseX::声明自己不是很容易扩展。我知道呀。我试过了

因此,考虑到所有这些,也因为我编写了Moops,我将使用它作为示例。在这里,我们定义了一个角色Kavorka::TraitFor::Sub::ProvidesMe,它将向方法中注入少量代码。然后,我们将该角色应用于使用does ProvideMe的方法。

代码语言:javascript
复制
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"
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23815446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档