| IOC documentation | Contained in the IOC distribution. |
IOC::Service - An IOC Service object
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 {
my $c = shift;
return FileLogger->new($c->get('log_file'));
}));
$container->register(IOC::Service->new('application' => sub {
my $c = shift;
my $app = Application->new();
$app->logger($c->get('logger'));
return $app;
}));
$container->get('application')->run();
In this IOC framework, the IOC::Service object holds instances of components to be managed.
+--------------+ +-------------------------+
| IOC::Service |---(instance)--->| <Your Component/Object> |
+--------------+ +-------------------------+
|
(parent_container)
|
V
+------------------+
| IOC::Container |
+------------------+
Creates a service with a $name, and uses the $block argument to initialize the service on demand.
Returns the name of the service instance.
Given a $container, which is an instance of IOC::Container or a subclass of it, this method will associate the service instance with that container object.
This will break the connection between a service and a container. This method is usually only called by the unregister method in IOC::Container.
This method returns the component held by the service object, the is basically the value returned by the $block constructor argument.
This method returns an IOC::Service::Deferred wrapper which will lazy load the service. This is used for handling circular dependencies, and rarely used directly.
None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it.
I use Devel::Cover to test the code coverage of my tests, see the CODE COVERAGE section of IOC for more information.
stevan little, <stevan@iinteractive.com>
Copyright 2004-2007 by Infinity Interactive, Inc.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| IOC documentation | Contained in the IOC distribution. |
package IOC::Service; use strict; use warnings; our $VERSION = '0.08'; use Scalar::Util qw(blessed); use IOC::Exceptions; sub new { my ($_class, $name, $block) = @_; my $class = ref($_class) || $_class; my $service = {}; bless($service, $class); $service->_init($name, $block); return $service; } sub _init { my ($self, $name, $block) = @_; (defined($name)) || throw IOC::InsufficientArguments "Service object cannot be created without a name"; (defined($block) && ref($block) eq 'CODE') || throw IOC::InsufficientArguments "Service object cannot be created without CODE block"; # set the defaults $self->{_instance} = undef; # assign constructor args $self->{name} = $name; $self->{block} = $block; # container is optional $self->{container} = undef; } 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__