Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 如何从属性';Moose的元对象是什么?_Perl_Serialization_Moose_Metaclass - Fatal编程技术网

Perl 如何从属性';Moose的元对象是什么?

Perl 如何从属性';Moose的元对象是什么?,perl,serialization,moose,metaclass,Perl,Serialization,Moose,Metaclass,我正在开发一个序列化工具,使用Moose读取和写入符合非标准格式的文件。现在,我根据类中对象的默认值确定如何加载下一项,但这有其自身的缺点。相反,我希望能够使用属性元类中的信息来生成正确类型的新值。我怀疑有一种方法可以确定“isa”限制是什么,并从中派生生成器,但我在Moose::Meta::Attribute或Class::MOP::Attribute中没有看到任何特定的方法可以帮助我 这里有一个更进一步的例子。假设我有以下课程: package Example; use Moose; us

我正在开发一个序列化工具,使用Moose读取和写入符合非标准格式的文件。现在,我根据类中对象的默认值确定如何加载下一项,但这有其自身的缺点。相反,我希望能够使用属性元类中的信息来生成正确类型的新值。我怀疑有一种方法可以确定“isa”限制是什么,并从中派生生成器,但我在Moose::Meta::Attribute或Class::MOP::Attribute中没有看到任何特定的方法可以帮助我

这里有一个更进一步的例子。假设我有以下课程:

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'