我试图在应用程序中使用MooseX::方法::签名和MooseX::声明,我需要在编译时(而不是在运行时)在每个方法的开头注入自定义代码:
而不是这样:
use MooseX::Declare;
method check ($value) {
$return $value;
}我希望在编译时在每个方法的开头注入一个代码,如下所示:
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;,我可以这样使用它:
method check ($value) {
say $me
}以下是修改过的方法::签名::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;
}发布于 2014-05-22 22:17:11
驼鸟和卡沃卡提供了一种与MooseX::Declare和MooseX::方法::签名几乎兼容的语法,并且设计得非常可扩展(甚至从内部!)通过特征。我将提请您注意以下MooseX文件一节::声明
警告:MooseX:是基于Devel::,最初是由实现的一个巨大的裂缝,其目的在于让核心开发人员因为其存在而感到不安,以至于他们在内核中实现了正确的关键字处理。 ..。 如果您想在新代码中使用声明式语法,请为了小猫的喜爱,给自己买一个最新的perl,然后看看Moops。
MooseX::声明自己不是很容易扩展。我知道呀。我试过了。
因此,考虑到所有这些,也因为我编写了Moops,我将使用它作为示例。在这里,我们定义了一个角色Kavorka::TraitFor::Sub::ProvidesMe,它将向方法中注入少量代码。然后,我们将该角色应用于使用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"https://stackoverflow.com/questions/23815446
复制相似问题