IOC
view release on metacpan or search on metacpan
lib/IOC/Service.pm view on Meta::CPAN
sub name {
my ($self) = @_;
return $self->{name};
}
sub setContainer {
my ($self, $container) = @_;
(blessed($container) && $container->isa('IOC::Container'))
|| throw IOC::InsufficientArguments "container argument is incorrect";
$self->{container} = $container;
$self;
}
sub removeContainer {
my ($self) = @_;
$self->{container} = undef;
$self;
}
sub instance {
my ($self) = @_;
unless (defined $self->{_instance}) {
(defined($self->{container}))
|| throw IOC::IllegalOperation "Cannot create a service instance without setting container";
my $instance = $self->{block}->($self->{container});
$self->{_instance} = $instance unless defined $self->{_instance};
(defined($self->{_instance}))
|| throw IOC::InitializationError "Service creation block returned undefined value";
}
return $self->{_instance};
}
sub deferred {
my ($self) = @_;
return IOC::Service::Deferred->new($self);
}
sub DESTROY {
my ($self) = @_;
# remove the connnection to the instance
# but do not attempt to DESTROY it, that
# should be left up to the instance itself
$self->{_instance} = undef if defined $self->{_instance};
# remove the container instance as well
# no need to DESTROY this either since
# not only could it still have other services
# in it, but it it highly likely that the
# call to DESTROY this object came from
# its container anyway
$self->{container} = undef if defined $self->{container};
}
package IOC::Service::Deferred;
use strict;
use warnings;
our $VERSION = '0.02';
use overload '%{}' => sub {
return $_[0] if (caller)[0] eq 'IOC::Service::Deferred';
$_[0] = $_[0]->{service}->instance();
$_[0]
},
'@{}' => sub { $_[0] = $_[0]->{service}->instance(); $_[0] },
'${}' => sub { $_[0] = $_[0]->{service}->instance(); $_[0] },
'&{}' => sub { $_[0] = $_[0]->{service}->instance(); $_[0] },
nomethod => sub {
$_[0] = $_[0]->{service}->instance();
return overload::StrVal($_[0]) if ($_[3] eq '""' && !overload::Method($_[0], $_[3]));
if (my $func = overload::Method($_[0], $_[3])) {
return $_[0]->$func($_[1], $_[2]);
}
throw IOC::MethodNotFound "Could not find a method for overloaded '$_[3]' operator";
};
use Scalar::Util qw(blessed);
sub new {
my ($class, $service) = @_;
(blessed($service) && $service->isa('IOC::Service'))
|| throw IOC::InsufficientArguments "You can only defer an IOC::Service object";
return bless { service => $service }, $class;
}
sub can {
$_[0] = $_[0]->{service}->instance();
(shift)->can(shift);
}
sub isa {
$_[0] = $_[0]->{service}->instance();
(shift)->isa(shift);
}
sub DESTROY { (shift)->{service} = undef }
sub AUTOLOAD {
my ($subname) = our $AUTOLOAD =~ /([^:]+)$/;
$_[0] = $_[0]->{service}->instance();
my $func = $_[0]->can($subname);
(ref($func) eq 'CODE')
|| throw IOC::MethodNotFound "You cannot call '$subname'";
goto &$func;
}
1;
__END__
=head1 NAME
IOC::Service - An IOC Service object
=head1 SYNOPSIS
use IOC::Service;
my $container = IOC::Container->new();
$container->register(IOC::Service::Literal->new('log_file' => "logfile.log"));
$container->register(IOC::Service->new('logger' => sub {
( run in 2.367 seconds using v1.01-cache-2.11-cpan-302cb4679cc )