本文介绍了如何在Perl中动态加载模块并执行方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm following up on this question about perl web services. I've managed to get modules loading and executing from a main program. Each of the modules is something like this:

#!/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; 

然后可以像这样完成这些模块的调用:

And invocation of these modules can then be done like this:

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的直接调用(该方法不起作用,但说明了我需要做的事情):

How would I get rid of the direct invocation of NiMbox::perlet:skeleton in a way in which I could do something that looks like this (which does not work but illustrates what I need to do):

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();
}

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

Since I'm very close I would rather see what is missing in this example rather than use another library. Any ideas?

推荐答案

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

I believe what you're looking for is Exporter or its many follow on modules. I see you're already using it in your module, but you're not using it to get %DEFINITION. You'd do that like so:

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的别名,并节省了大量输入.

That aliases %NiMbox::perlet::skeleton::DEFINITION to %DEFINITION and saves a bunch of typing.

要使用%DEFINITION的变量定义,可以使用符号引用"按名称引用变量...但是这些变量充满了危险.同样,导出全局变量意味着一次只能在一个给定的命名空间中只有一个.我们可以做得更好.

To be able to use a variable definition of %DEFINITION you could use "symbolic references" to refer to the variable by name... but those are fraught with peril. Also, exporting global variables means you can only have one at a time in a given namespace. We can do better.

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

What I would suggest is instead changing the %DEFINITION hash into the definition() class method which returns a reference to %DEFINITION. You could return a hash, but the reference avoids wasting time copying.

package NiMbox::perlet::skeleton;

use strict;
use warnings;

my %DEFINITION = ...;

sub definition {
    return \%DEFINITION;
}

现在您可以调用该方法并获取哈希引用.

Now you can call that method and get the hash ref.

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 可以为您更好地解决这一问题.

Doing it dynamically, the only trick is to load the class. You can eval "require $class" or die $@ but that has security implications. UNIVERSAL::require or Module::Load can handle that better for you.

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中动态加载模块并执行方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-24 16:34