动态加载Perl模块 [英] Dynamically loading Perl modules

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

问题描述

我正在尝试制作一个可扩展的系统,我可以编写一个新的模块来作为一个处理程序。我希望程序自动加载放入Handlers目录并符合Moose :: Role界面的任何新的.pm文件。



我想知道是否有是一个Perl模块还是更多的Moose认证方式自动执行?这是我迄今为止所建立的,但似乎有点冗长,而且必须有一个更简单的方法。



处理程序.pl 包含:

 #!/ usr / bin / perl 
use Handler;
使用Data :: Dumper;

我的$ base_handler = Handler-> new();
$ base_handler-> load_modules('SysG / Handler');
print Dumper($ base_handler);

Handler.pm 包含:

  package Handler; 
使用麋;

有'handlers'=> (traits => ['Array'],handles => {add_handler =>'push'});

sub load_modules {
my($ self,$ dir)= @_;

push(@INC,$ dir);

我的@modules = find_modules_to_load($ dir);
eval {
#请注意,这种排序很重要。处理顺序将至关重要。
#排序意味着排序顺序
foreach我的$ module(sort @modules){
(我的$ file = $ module)=〜s | :: | / | g;
print关于加载$ file.pm for module $ module\\\
;
需要$文件。 '。下午';
$ module-> import();
my $ obj = $ module-> new();
$ self-> add_handler($ obj);
1;
}
}或做{
我的$错误= $ @;
print加载模块时出错:$ errorif $ error;
};

}

sub find_modules_to_load {
my($ dir)= @_;
我的@files = glob($ dir / *。pm);
我的$ namespace = $ dir;
$ namespace =〜s / \ // :: / g;

#获取叶子名称并添加System :: Module命名空间
my @modules = map {s /.* \ /(.*)。pm // g; $ {命名空间} :: $ 1; } @files;
dieERROR:在$ dir\\\
中找不到分类器模块,除非@modules;
return @modules;
}

1;

然后我创建了一个名为SysG / Handler的目录,并添加了两个.pm文件,通常将符合一个Moose ::角色(好像定义一个必须被粘贴的界面)。



SysG :: Handler :: 0001_HandleX.pm stub包含:

 包SysG :: Handler :: 0001_HandleX; 
使用麋;
1;

SysG :: Handler :: 0002_HandleX.pm stub包含:

 包SysG :: Handler :: 0002_HandleY; 
使用麋;
1;将所有这一切放在一起,Data :: Dumper的结果是:

  $ VAR1 = bless({
'handlers'=> [
bless({},'SysG :: Handler :: 0001_HandleX '),
bless({},'SysG :: Handler :: 0002_HandleY')
]
},'Handler');

所以,现在我重复一下我的原始问题:必须有一个更简单的方法,或一个模块或任何Moose专家能够在这里帮助吗?

解决方案

MooseX :: Object ::可插拔


I am trying to make an extensible system whereby I can code up a new module to be a handler. I want the program to automatically load any new .pm file that is put into the Handlers directory and conforms to a Moose::Role interface.

I'm wondering whether there is a Perl module or a more Moose sanctioned way to do this automatically? Here is what I have built so far, but it seems a little verbose and there has got to be a simpler way to do it.

handler.pl contains:

    #!/usr/bin/perl
            use Handler;
    use Data::Dumper;

    my $base_handler = Handler->new();
    $base_handler->load_modules('SysG/Handler');
    print Dumper($base_handler);

Handler.pm contains:

    package Handler;
    use Moose;

    has 'handlers' => ( traits => ['Array'], handles => { add_handler => 'push' } );

    sub load_modules {
        my ($self,$dir) = @_;

        push(@INC, $dir);

        my @modules = find_modules_to_load($dir);
        eval { 
            # Note that this sort is important. The processing order will be critically important.
            # The sort implies the sort order
            foreach my $module ( sort @modules) {
                (my $file = $module) =~ s|::|/|g;
                print "About to load $file.pm for module $module\n" ;
                require $file . '.pm';
                $module->import();
                my $obj = $module->new();
                $self->add_handler($obj);
                1;
            }
        } or do {
            my $error = $@;
            print "Error loading modules: $error" if $error;
        };

    }

    sub find_modules_to_load {
        my ($dir) = @_;
        my @files = glob("$dir/*.pm");
        my $namespace = $dir;
        $namespace =~ s/\//::/g;

        # Get the leaf name and add the System::Module namespace to it
        my @modules = map { s/.*\/(.*).pm//g;  "${namespace}::$1"; } @files;
        die "ERROR: No classifier modules found in $dir\n" unless @modules;
        return @modules;
    }

    1;

Then I have made a directory called SysG/Handler and added two .pm files which ordinarily will conform to a Moose::Role (as if to define an interface that must be adhered too).

The SysG::Handler::0001_HandleX.pm stub contains:

package SysG::Handler::0001_HandleX;
use Moose;
1;

The SysG::Handler::0002_HandleX.pm stub contains:

package SysG::Handler::0002_HandleY;
use Moose;
1;

Put all this together and the Data::Dumper result is:

$VAR1 = bless( {
             'handlers' => [
                             bless( {}, 'SysG::Handler::0001_HandleX' ),
                             bless( {}, 'SysG::Handler::0002_HandleY' )
                           ]
           }, 'Handler' );

So, now I repeat my original question: There must be a simpler way, or a module or a Moose way to automatically load any modules in a specific directory.

Any Moose experts able to help out here?

解决方案

MooseX::Object::Pluggable

这篇关于动态加载Perl模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆