我正在关注这个有关perl网络服务的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();
}
由于我非常接近,我宁愿看到这个例子中缺少的东西,而不是使用另一个库。有什么想法吗?
答案 0 :(得分:3)
如果您想使类名称动态化,您可以执行以下操作:
my $class = 'NiMbox::perlet::' . $perlet;
my $class_file = $class;
$class_file =~ s{::}{/};
$class_file .= '.pm';
require $class_file;
$class->import;
(或者甚至更好,使用Module::Load作为@Schwern suggests。
获取%DEFINITION
类有点棘手,因为它涉及符号引用。更好的方法是提供一个返回它的类方法,例如
package NiMbox::perlet::skeleton;
...
sub definition {
my %definition;
$definition{main} = { summary => 'skeleton main', ... };
return %definition;
}
然后你可以这样做:
my %DEFINITION = $class->definition;
foreach my $s( keys %DEFINITION ) {
print "calling sub '$s'\n";
$class->$s;
}
答案 1 :(得分:3)
我相信你所寻找的是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
的变量定义,您可以使用“符号引用”来按名称引用变量......但这些都充满了危险。此外,导出全局变量意味着您在给定的命名空间中一次只能有一个变量。我们可以做得更好。
我建议的是将%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::require或Module::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();
}