Я работаю над инструментом сериализации, используя Moose для чтения и записи файла, который соответствует нестандартному формату. Сейчас я определяю, как загрузить следующий элемент на основе значений по умолчанию для объектов в классе, но у него есть свои недостатки. Вместо этого я хотел бы использовать информацию в метаклассе атрибута для генерации нового значения правильного типа. Я подозреваю, что есть способ определить, что такое ограничение isa, и получить от него генератор, но я не видел особых методов в Moose :: Meta :: Attribute или Class :: MOP :: Attribute, которые могли бы мне помочь.Как создать экземпляр значения из мета-объекта атрибута с помощью Moose?
Вот еще несколько примеров. Скажем, у меня есть следующий класс:
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>);
}
}
}
Но, как вы можете видеть на # <-- ERROR PRONE PROBLEM HERE!
, весь этот процесс зависит от наличия значение в атрибут для начала! Если значение равно undef, у меня нет указаний относительно , который загружается. Я хотел бы заменить $attribute->get_value($self)
на способ получения информации о типе значения, которое нужно загрузить. Моя проблема в том, что документы, с которыми я связан выше для Class::MOP::Attribute
и Moose::Meta::Attribute
, похоже, не имеют способа получить объект типа, который должен получить атрибут.
Информация о типе для атрибута - это в основном то, к чему я пытаюсь добраться.
(Примечание для будущих читателей:.. Здесь ответ заставил меня начать, но это не окончательное решение в себя Вам придется копаться в Moose::Meta::TypeConstraint
классов на самом деле делать то, что я ищу здесь)
Type_constraint - aha! Я думаю, что все! –
Хорошо, спасибо за то, что вы на правильном пути. Пора спросить лучшую форматированную версию вопроса. :) –
Рад помочь. Я только знал об атрибуте $ attribute-> type_constraint, когда я прочитал это превосходное сообщение в блоге Sartak: http://blog.sartak.org/2009/06/mooses-mop-schematize.html – draegtun