我希望能够创建“幽灵”包和潜艇。我有一个配置(ini)文件,其中的条目如下:
[features]
sys.ext.latex = off
gui.super.duper.elastic = off
user.login.rsa = on
解析此文件,以后开发人员可以提出以下问题:
if ( MyApp::Feature->enabled ( 'user.login.rsa' ) { ... }
(整个想法基于Martin Fowler的FeatureToggle http://martinfowler.com/bliki/FeatureToggle.html)
使用AUTOLOAD捕获MyApp :: Feature中的调用,使用BEGIN块解析ini文件,我们可以提供此API:
if ( MyApp::Feature->user_login_rsa ) { ... }
问题是:是否可以创建以下API:
if ( MyApp::Feature::User::Login::RSA ) { ... }
只有MyApp :: Feature?
可以在配置文件中修改大小写,这不是问题所在。并说清楚,实现与配置分离,没有MyApp :: Feature :: User :: Login :: RSA,永远不会。该功能的实现在于f.e.在MyApp :: Humans。
我知道把MyApp :: Feature :: Foo :: Bar建议必须有这样的Package。但是开发人员知道功能包管理功能切换的惯例,他们没有问题。我找到了第一个例子(使用enabled($ string)位太复杂而无法读取
if ( package::package->method ( string ) )
第二个更好:
if ( package::package->method )
第三个会更容易:
if ( package::package::package )
那么,是否可以在包级别上模拟AUTOLOAD?
问候, 罗布。
答案 0 :(得分:4)
所以听起来你有一个想要安装到命名空间中的多字键列表。
BEGIN {
my %states = ( # the values that should be transformed
on => sub () {1},
off => sub () {''},
);
sub install_config {
my ($package, $config) = @_;
for my $key (keys %$config) {
my @parts = map ucfirst, split /\./, $key;
my $name = join '::' => $package, @parts;
no strict 'refs';
*{$name} = $states{$$config{$key}} # use a tranformed value
|| sub () {$$config{$key}} # or the value itself
}
}
}
BEGIN {
my %config = qw(
sys.ext.latex off
gui.super.duper.elastic off
user.login.rsa on
some.other.config other_value
);
install_config 'MyApp::Feature' => \%config;
}
say MyApp::Feature::Sys::Ext::Latex ? 'ON' : 'OFF'; # OFF
say MyApp::Feature::Gui::Super::Duper::Elastic ? 'ON' : 'OFF'; # OFF
say MyApp::Feature::User::Login::Rsa ? 'ON' : 'OFF'; # ON
say MyApp::Feature::Some::Other::Config; # other_value
这里安装的常量子程序将在适用时由perl内联。
通过将install_config
放入包的导入功能,可以使BEGIN {$INC{'Install/Config.pm'}++} # fool require
sub Install::Config::import {shift; goto &install_config}
use Install::Config 'MyApp::Feature' => {qw(
sys.ext.latex off
gui.super.duper.elastic off
user.login.rsa on
some.other.config other_value
)};
更容易使用:
{{1}}