私は、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
ロールでは、クラスのメタオブジェクトを反復処理して、使用可能なすべての属性を確認し、Order特性を持つ属性のみを選択できます。
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>);
}
}
}
ただし、でわかるように# <-- ERROR PRONE PROBLEM HERE!
、このプロセス全体は、最初に属性に値があることに依存しています。値がundefの場合、何をロードするかはわかりません。$attribute->get_value($self)
代わりに、ロードする必要のある値のタイプに関する情報を取得する方法に置き換えたいと思います。私の問題は、上記でリンクしたドキュメントClass::MOP::Attribute
がMoose::Meta::Attribute
、属性が取得するはずのオブジェクトのタイプを取得する方法がないように見えることです。
属性のタイプ情報は、基本的に私が取得しようとしているものです。
Moose::Meta::TypeConstraint
(将来の読者への注意:ここでの答えは私を始めましたが、それ自体が最終的な解決策ではありません。私がここで探していることを実際に行うには、クラスを掘り下げる必要があります。)