view lib/IMPL/Config/Container.pm @ 417:3ed0c58e9da3 ref20150831

working on di container, tests
author cin
date Mon, 02 Nov 2015 01:56:53 +0300
parents 3d24b10dd0d5
children 3f38dabaf5cc
line wrap: on
line source

package IMPL::Config::Container;
use strict;

use IMPL::Exception();
use IMPL::lang qw(:base);
use IMPL::declare {
	require => {
		Descriptor        => 'IMPL::Config::Descriptor',
		ValueDescriptor   => 'IMPL::Config::ValueDescriptor',
		ActivationContext => 'IMPL::Config::ActivationContext',
		Hierarchy         => 'IMPL::Config::Hierarchy',
		Bag               => 'IMPL::Config::Bag',
		Loader            => 'IMPL::Code::Loader'
	},
	base => [
		'IMPL::Object' => undef
	],
	props => [
		roles     => 'r',
		services  => 'r',
		instances => 'r',
		parent    => 'r',
		root      => 'r',
		loader    => 'r'
	]
};

my $nextRoleId = 1;

sub CTOR {
	my ( $this, $parent, %opts ) = @_;

	$this->instances( {} );

	$this->loader( $opts{loader} || Loader->safe );

	if ($parent) {
		$this->roles( Hierarchy->new( $parent->roles ) );
		$this->services( Bag->new( $parent->services ) );
		$this->parent($parent);
		$this->root( $parent->root );
	}
	else {
		$this->roles( Hierarchy->new() );
		$this->services( Bag->new() );
		$this->root($this);
	}
}

sub Require {
	my ($this, $class) = @_;
	
	return $this->loader->Require($class);
}

sub Register {
	my ( $this, $role, $service ) = @_;

	die IMPL::InvalidArgumentException->new('service')
	  unless is( $service, Descriptor );
	$this->services->Register( $this->GetLinearRoleHash($role), $service );
}

sub GetLinearRoleHash {
	my ( $this, $role ) = @_;

	die IMPL::InvalidArgumentException->new(
		role => 'The argument is required' )
	  unless $role;

	if ( isarray($role) ) {
		my $tempRole = "unnamed-" . $nextRoleId++;
		$this->roles->AddRole( $tempRole, $role );
		$role = $tempRole;
	}

	$this->roles->GetLinearRoleHash($role);
}

sub Resolve {
	my ( $this, $role, %opts ) = @_;

	my $descriptor = $this->services->Resolve($role);

	return $descriptor->Activate( ActivationContext->new($this) )
	  if $descriptor;

	return $opts{default} if exists $opts{default};
}

sub ResolveAll {
	my ( $this, $role, %opts ) = @_;

	my $all = $this->services->ResolveAll($role);

	my $context;

	my @result;

	foreach my $service (@$all) {
		$context = ActivationContext->new($this)
		  unless $context || $opts{shared};

		push @result, $service->Activate($context);
	}

	return \@result;
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Config::Container> - dependency injection container

=head1 SYNOPSIS

=head2 METHODS

=head3 Resolve($role)

=head3 ResolveAll($role, shared => $useSharedContext)

=head3 Register($role, $service)

=cut