Mercurial > pub > Impl
view lib/IMPL/Config/ActivationContext.pm @ 427:09e0086a82a7 ref20150831 tip
Merge
author | cin |
---|---|
date | Tue, 15 May 2018 00:51:33 +0300 |
parents | b0481c071bea |
children |
line wrap: on
line source
package IMPL::Config::ActivationContext; use IMPL::lang qw(:base); use IMPL::Exception(); use IMPL::declare { require => { Bag => 'IMPL::Config::Bag', ServiceNotFoundException => 'IMPL::Config::ServiceNotFoundException', Descriptor => '-IMPL::Config::Descriptor' }, base => { 'IMPL::Object' => '@_' }, props => [ container => 'rw', owner => 'rw', instances => 'rw', name => 'rw', _services => 'rw', _stack => 'rw' ] }; sub CTOR { my ( $this, $container ) = @_; $this->container($container) or die IMPL::InvalidArgumentException->new('container'); $this->owner($container); $this->_services( $container->services ); $this->instances( {} ); $this->_stack( [] ); } sub EnterScope { my ( $this, $name, $services, $container ) = @_; my $info = { name => $this->name }; $this->name($name); if ( $container && $this->container != $container ) { $info->{container} = $this->container; $this->container($container); } if ($services) { die IMPL::InvalidArgumentException->new( services => 'An array is required' ) unless isarray($services); my $bag = $this->container->serviceCache->{ ref($services) }; unless ($bag) { $bag = Bag->new( $this->_services ); $bag->tag( $container || $this->container ); $bag->Register( $container->GetLinearRoleHash( $_->{role} ), $_->{descriptor} ) foreach @$services; $container->serviceCache->{ ref($services) } = $bag; } $info->{services} = $this->_services; $this->_services($bag); } push @{ $this->_stack }, $info; } sub LeaveScope { my ($this) = @_; my $info = pop @{ $this->_stack } or die IMPL::InvalidOperationException->new(); $this->name( $info->{name} ); $this->_services( $info->{services} ) if $info->{services}; $this->conatiner( $info->{container} ) if $info->{container}; } sub Resolve { my ( $this, $role, %opts ) = @_; #change of the container may occur only due resolution of the dependency my ( $d, $bag ) = $this->_services->Resolve($role); unless ($d) { die ServiceNotFoundException->new(serviceName => $role) unless $opts{optional}; return $opts{default}; } else { $this->EnterScope( $d->GetName(), $d->services(), $bag->tag() ); my $instance = $d->Activate($this); $this->LeaveScope(); return $instance; } } sub Activate { my ( $this, $d ) = @_; $this->EnterScope( $d->GetName(), $d->services() ); my $instance = $d->Activate($this); $this->LeaveScope(); return $instance; } sub Clone { my ($this) = @_; my $clone = SELF->new( $this->owner ); $clone->name($this->name); $clone->container( $this->container ); $clone->_services( $this->_services ); $clone->instances( $this->instances ); $clone->_stack( [ @{ $this->_stack } ] ); return $clone; } 1; __END__ =pod =head1 NAME C<IMPL::Config::ActivationContext> - an activation context for the service =head1 SYNOPSIS For the internal use only =head1 MEMBERS =head2 PROPERTIES =head3 [get] container Current container for the activation context, this container changes during resolution process to match the one in which the resulting descriptor were defined. Descriptors can use this property to access the cache of theirs container. =head3 [get] owner The container which created this context. Descriptors can use this property during theirs activation. =head3 [get] instances The activation cache which can be used to store instances during single resolution process. =head2 METHODS =head3 Resolve($serviceId): $instance Activates and returns an instance specified by C<$serviceId> =head3 Activate($descriptor): $instance Activates and returns an instance of the services for the specified descriptor/ =cut