我正在尝试使用MooseX::Method::Signatures和 MooseX::Declare在应用程序中,我的需要是在编译时而不是运行时在每个方法的开头注入(inject)自定义代码:
而不是这个:
use MooseX::Declare;
method check ($value) {
$return $value;
}
我想在编译时在每个方法的开头注入(inject)一段代码,如下所示:
method check ($value) {
my ($value) = $self->validate($value);
$return $value;
}
现在我想要代码
my ($value) = $self->validate($value);
在编译时而不是运行时使用 MooseX::Decalre 模块在包中所有方法的开头自动注入(inject),我的意思是不使用 Moose 方法修饰符之前、之后、周围等。
这需要对这些模块进行修改,但我需要有人告诉我从哪里开始。
我能够修改模块 Method::Signatures::Simple为此,我给作者发了邮件要求修改,但没有得到回复。即使经过修改我也无法使用它,因为它不支持类型检查和像 MooseX::Declare 这样的默认值。
模块的修改版本Method::Signatures::Simple以下供引用,我的使用方式如下:
use Method::Signatures::Simple (method => 'method,action', function => 'function', invocant=>'$this', 'inject'=>'my ($me) = $this->me;');
现在在所有方法中,我都注入(inject)了代码 my ($me) = $this->me;
,我就可以这样使用它:
method check ($value) {
say $me
}
这是修改后的 Method::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;
}
最佳答案
Moops和 Kavorka提供与 MooseX::Declare 和 MooseX::Method::Signatures 几乎兼容的语法,并且被设计为通过特征非常可扩展(甚至从内部!)。我会提请您注意以下section of documentation for MooseX::Declare :
Warning: MooseX::Declare is based on Devel::Declare, a giant bag of crack originally implemented by mst with the goal of upsetting the perl core developers so much by its very existence that they implemented proper keyword handling in the core.
[...]
If you want to use declarative syntax in new code, please for the love of kittens get yourself a recent perl and look at Moops instead.
MooseX::Declare 本身并不是很容易扩展。我知道。 I've tried .
因此请牢记所有这些,并且因为我写了 Moops,所以我将使用它作为示例。这里我们定义了一个角色 Kavorka::TraitFor::Sub::ProvidesMe
,它将向方法中注入(inject)一点代码。然后,我们将该角色应用到使用 does ProvideMe
的方法。
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"
关于Perl MooseX::Method::Signatures 将自定义代码注入(inject)所有方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23815446/