Perl 如何从属性';Moose的元对象是什么?
我正在开发一个序列化工具,使用Moose读取和写入符合非标准格式的文件。现在,我根据类中对象的默认值确定如何加载下一项,但这有其自身的缺点。相反,我希望能够使用属性元类中的信息来生成正确类型的新值。我怀疑有一种方法可以确定“isa”限制是什么,并从中派生生成器,但我在Moose::Meta::Attribute或Class::MOP::Attribute中没有看到任何特定的方法可以帮助我 这里有一个更进一步的例子。假设我有以下课程:Perl 如何从属性';Moose的元对象是什么?,perl,serialization,moose,metaclass,Perl,Serialization,Moose,Metaclass,我正在开发一个序列化工具,使用Moose读取和写入符合非标准格式的文件。现在,我根据类中对象的默认值确定如何加载下一项,但这有其自身的缺点。相反,我希望能够使用属性元类中的信息来生成正确类型的新值。我怀疑有一种方法可以确定“isa”限制是什么,并从中派生生成器,但我在Moose::Meta::Attribute或Class::MOP::Attribute中没有看到任何特定的方法可以帮助我 这里有一个更进一步的例子。假设我有以下课程: package Example; use Moose; us
package Example;
use Moose;
use My::Trait::Order;
use My::Class;
with 'My::Role::Load', 'My::Role::Save';
has 'foo' => (
traits => [ 'Order' ],
isa => 'Num',
is => 'rw',
default => 0,
order => 1,
);
has 'bar' => (
traits => [ 'Order' ],
isa => 'ArrayRef[Str]',
is => 'rw',
default => sub { [ map { "" } 1..8 ] }
order => 2,
);
has 'baz' => (
traits => [ 'Order' ],
isa => 'Custom::Class',
is => 'rw',
default => sub { Custom::Class->new() },
order => 3,
);
__PACKAGE__->meta->make_immutable;
1;
(进一步说明:My::Role::Load
和My::Role::Save
实现此文件类型的序列化角色。它们迭代所附加到的类的属性,并查看属性类以获取序列化顺序。)
在My::Role::Load
角色中,我可以迭代类的元对象,查看所有可用的属性,并只选择那些具有我的订单特征的属性:
package My::Role::Load;
use Moose;
...
sub load {
my ($self, $path) = @_;
foreach my $attribute ( $self->meta->get_all_attributes ) {
if (does_role($attribute, 'My::Trait::Order') ) {
$self->load_attribute($attribute) # do the loading
}
}
}
现在,我需要知道元属性表示的属性的isa
。现在,我通过获取一个实例来测试它,并用类似这样的东西进行测试:
use 5.010_001; # need smartmatch fix.
...
sub load_attribute {
my ($self, $attribute, $fh) = @_;
my $value = $attribute->get_value($self); # <-- ERROR PRONE PROBLEM HERE!
if (ref($value) && ! blessed($value)) { # get the arrayref types.
given (ref($value)) {
when('ARRAY') {
$self->load_array($attribute);
}
when('HASH') {
$self->load_hash($attribute);
}
default {
confess "unable to serialize ref of type '$_'";
}
}
}
else {
when (\&blessed) {
confess "don't know how to load it if it doesn't 'load'."
if ! $_->can('load');
$_->load();
}
default {
$attribute->set_value($self, <$fh>);
}
}
}
使用5.010_001;#需要smartmatch修复。
...
子加载属性{
我的($self,$attribute,$fh)=@;
我的$value=$attribute->get_value($self);#加载_数组($attribute);
}
when('HASH'){
$self->load_hash($attribute);
}
违约{
坦白“无法序列化“$”类型的引用;
}
}
}
否则{
何时(\&祝福){
承认“如果它不‘加载’,就不知道如何加载。”
如果!$\->can('load');
$\->load();
}
违约{
$attribute->set_值($self,);
}
}
}
但是,正如您在
#上看到的,我不太确定自己是否理解(也许您可以包含一些伪代码来演示您正在寻找的内容),但听起来,通过定义一个新的属性trait,您可能会获得想要的行为:设置您的属性,以便类上的一组方法委托给属性的对象(isa=>'MySerializer',handles=>[qw(methods)]
)
您可能还需要子类化(或者更好地,向其中添加一个角色),以增强add\u attribute()
的行为
编辑:如果查看源代码(特别是\u process\u options
方法),您将看到isa
选项由进行处理,以返回要存储在对象的type\u约束
字段中的实际类型。这将是一个对象,您可以对其调用is\u a\u type\u of()
此字段可通过Moose::Meta::Attribute中的type_constraint
方法获得。查看所有可用于检查属性类型的接口。不确定我是否遵循了您的要求,或者强制可能会执行您想要的操作
但是,要获得属性isa:
/I3az/出于好奇,为什么不使用/扩展?它进行序列化,并且已经有大约两年半的时间了。至少,MooseX::Storage将向您展示如何为Moose编写一个(经过良好测试且已准备好生产的)序列化引擎。Type_constraint-aha!我想就是这样!好的,谢谢你让我走上正轨。是时候问一个格式更好的问题了。:)很高兴能帮上忙。当我读到Sartak的这篇优秀博文时,我才知道$attribute->type_约束:
{
package Foo;
use Moose;
has 'bar' => ( isa => 'Str', is => 'rw' );
}
my $foo = Foo->new;
say $foo->meta->get_attribute('bar')->type_constraint; # => 'Str'