2011-06-29 12 views
2

perlのWebサービスに関するこのquestionをフォローしています。私はメインプログラムからモジュールを読み込んで実行するようになった。動的にモジュールをロードしてperlでメソッドを実行する方法

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

私は非常に近いですので、私はむしろ欠けているものを見るだろうこの例では別のライブラリを使用するのではなく、何か案は?

答えて

3

私は何を探していることはExporterであるか、その多くは、モジュールに続くと信じて:は、その後、あなたのような何かを行うことができます。あなたのモジュールですでにそれを使用していますが、それを使用して%DEFINITIONを取得していないことがわかります。あなたはやると思いますので、そのような:%DEFINITION%NiMbox::perlet::skeleton::DEFINITIONをエイリアスやタイピングの束を保存し

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

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

%DEFINITIONの変数定義を使用できるようにするには、変数を名前で参照するために "シンボリックリファレンス"を使用できますが、それは危険に満ちています。また、グローバル変数をエクスポートすると、指定された名前空間内に一度に1つしか存在できないことを意味します。私たちはより良いことができます。

代わりに%DEFINITIONハッシュを%DEFINITIONへの参照を返す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 [email protected]でも可能ですが、それはセキュリティ上の意味合いがあります。 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(); 
} 
+0

ありがとうございました。私が取り除く必要があるのは、最後の 'NiMbox :: perlet :: skeleton'だけです。このようにして、モジュールの名前を変数にすることができ、 'skeleton'パッケージの' main'サブを呼び出す 'docall skeleton main'のように呼び出すことができます。 – rmarimon

+0

'$ class - > $ s()'を使うだけです。 – rmarimon

+1

@rmarimonはい、それは私の見解です。 – Schwern

3

あなたはクラス名を動的にしたい場合は、あなたがこのような何か行うことができます。

my $class = 'NiMbox::perlet::' . $perlet; 
my $class_file = $class; 
$class_file =~ s{::}{/}; 
$class_file .= '.pm'; 

require $class_file; 
$class->import; 

(またはより良い、@Schwern suggestsとしてModule::Loadを使用し

%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; 
} 
関連する問題