动态加载 Perl 模块

发布于 2024-12-18 22:58:43 字数 2616 浏览 2 评论 0原文

我正在尝试创建一个可扩展的系统,通过该系统我可以将新模块编码为处理程序。我希望程序自动加载放入 Handlers 目录并符合 Moose::Role 接口的任何新 .pm 文件。

我想知道是否有 Perl 模块或更多 Moose 认可的方法来自动执行此操作?这是我到目前为止所构建的,但它看起来有点冗长,必须有一种更简单的方法来做到这一点。

handler.pl 包含:

    #!/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 包含:

    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;

然后我创建了一个名为 SysG/Handler 的目录,并添加了两个 .pm 文件,这些文件通常符合 Moose::Role (就像定义一个也必须遵守的接口一样)。

SysG::Handler::0001_HandleX.pm 存根包含:

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

SysG::Handler::0002_HandleX.pm 存根包含:

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

将所有这些放在一起以及 Data::Dumper结果是:

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

所以,现在我重复我原来的问题:必须有一个更简单的方法,或者一个模块或一个Moose方法来自动加载特定目录中的任何模块。

有哪位麋鹿专家可以帮忙吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文