我正在跟踪有关perl Web服务的question。我设法从主程序加载和执行模块。每个模块都是这样的:

#!/usr/bin/perl
package NiMbox::perlet::skeleton;

use strict;
use warnings;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(%DEFINITION main secondary);

our %DEFINITION;
$DEFINITION{'main'} = {
    summary => 'skeleton main',
    description => 'long skeleton main description',
    args => { 'box' => {}, 'other' => {} }
};
$DEFINITION{'secondary'} = {
    summary => 'skeleton secondary',
    description => 'long skeleton secondary description'
};

sub main {
    print "main...\n";
}

sub secondary {
    print "secondary...\n"
}

1;

然后可以像下面这样完成这些模块的调用:
use NiMbox::perlet::skeleton;

my %DEFINITION = %NiMbox::perlet::skeleton::DEFINITION;
foreach my $s (keys %DEFINITION) {
    print "calling sub '$s'\n";
    NiMbox::perlet::skeleton->$s();
}

我如何以一种可以执行类似以下操作的方式摆脱NiMbox::perlet:skeleton的直接调用(该方法不起作用,但说明了我需要做的事情):
my $perlet = 'skeleton';

use NiMbox::perlet::$perlet;

my %DEFINITION = %NiMbox::perlet::$perlet::DEFINITION;
foreach my $s (keys %DEFINITION) {
    print "calling sub '$s'\n";
    NiMbox::perlet::$perlet->$s();
}

由于我非常接近,所以我宁愿查看此示例中缺少的内容,也不愿使用其他库。有任何想法吗?

最佳答案

我相信您正在寻找的是Exporter或它的许多后续模块。我看到您已经在模块中使用它了,但是您没有使用它来获取%DEFINITION。您可以这样做:

use NiMbox::perlet::skeleton qw(%DEFINITION);

foreach my $s (keys %DEFINITION) {
    print "calling sub '$s'\n";
    NiMbox::perlet::skeleton->$s();
}

这将%NiMbox::perlet::skeleton::DEFINITION别名为%DEFINITION并节省了大量输入。

为了能够使用%DEFINITION的变量定义,您可以使用“符号引用”通过名称来引用变量...但是这些变量充满了危险。同样,导出全局变量意味着一次只能在给定的 namespace 中只有一个。我们可以做得更好。

我的建议是改为将%DEFINITION哈希更改为definition()类方法,该方法返回对%DEFINITION的引用。您可以返回散列,但是参考避免浪费时间复制。
package NiMbox::perlet::skeleton;

use strict;
use warnings;

my %DEFINITION = ...;

sub definition {
    return \%DEFINITION;
}

现在,您可以调用该方法并获取哈希引用。
use NiMbox::perlet::skeleton;

my $definition = NiMbox::perlet::skeleton->definition;

foreach my $s (keys %$definition) {
    print "calling sub '$s'\n";
    NiMbox::perlet::skeleton->$s();
}

动态地执行此操作,唯一的技巧是加载类。您可以eval "require $class" or die $@,但这会带来安全隐患。 UNIVERSAL::requireModule::Load可以为您更好地处理该问题。
use Module::Load;

my $class = 'NiMbox::perlet::skeleton';
load $class;

my $definition = $class->definition;

foreach my $s (keys %$definition) {
    print "calling sub '$s'\n";
    $class->$s();
}

关于perl - 如何在Perl中动态加载模块并执行方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6525524/

10-13 03:57