407
|
1 package IMPL::Config::Container;
|
412
|
2 use strict;
|
|
3
|
420
|
4 use Scalar::Util qw(blessed);
|
413
|
5 use IMPL::Exception();
|
412
|
6 use IMPL::lang qw(:base);
|
|
7 use IMPL::declare {
|
420
|
8 require => {
|
|
9 Descriptor => 'IMPL::Config::Descriptor',
|
|
10 ActivationContext => 'IMPL::Config::ActivationContext',
|
|
11 Hierarchy => 'IMPL::Config::Hierarchy',
|
|
12 Bag => 'IMPL::Config::Bag',
|
|
13 Loader => 'IMPL::Code::Loader'
|
|
14 },
|
|
15 base => [
|
|
16 'IMPL::Object' => undef,
|
|
17 'IMPL::Object::Disposable' => undef
|
|
18 ],
|
|
19 props => [
|
|
20 roles => 'r',
|
|
21 services => 'r',
|
|
22 instances => 'r',
|
|
23 parent => 'r',
|
|
24 root => 'r',
|
|
25 loader => 'r'
|
|
26 ]
|
412
|
27 };
|
|
28
|
|
29 my $nextRoleId = 1;
|
|
30
|
413
|
31 sub CTOR {
|
420
|
32 my ( $this, $parent, %opts ) = @_;
|
413
|
33
|
420
|
34 $this->instances( {} );
|
413
|
35
|
420
|
36 $this->loader( $opts{loader} || Loader->safe );
|
415
|
37
|
420
|
38 if ($parent) {
|
|
39 $this->roles( Hierarchy->new( $parent->roles ) );
|
|
40 $this->services( Bag->new( $parent->services ) );
|
|
41 $this->parent($parent);
|
|
42 $this->root( $parent->root );
|
|
43 }
|
|
44 else {
|
|
45 $this->roles( Hierarchy->new() );
|
|
46 $this->services( Bag->new() );
|
|
47 $this->root($this);
|
|
48 }
|
|
49 }
|
|
50
|
|
51 sub Dispose {
|
|
52 my ($this) = @_;
|
|
53
|
|
54 my $d;
|
|
55 foreach my $v ( values %{ $this->instances } ) {
|
|
56 if ( $d = blessed($v) && $v->can('Dispose') ) {
|
|
57 &$d($v);
|
|
58 }
|
|
59 }
|
413
|
60 }
|
412
|
61
|
417
|
62 sub Require {
|
420
|
63 my ( $this, $class ) = @_;
|
|
64
|
|
65 return $this->loader->Require($class);
|
417
|
66 }
|
|
67
|
412
|
68 sub Register {
|
420
|
69 my ( $this, $role, $service ) = @_;
|
413
|
70
|
420
|
71 die IMPL::InvalidArgumentException->new('service')
|
|
72 unless is( $service, Descriptor );
|
|
73 $this->services->Register( $this->GetLinearRoleHash($role), $service );
|
415
|
74 }
|
|
75
|
|
76 sub GetLinearRoleHash {
|
420
|
77 my ( $this, $role ) = @_;
|
415
|
78
|
420
|
79 die IMPL::InvalidArgumentException->new(
|
|
80 role => 'The argument is required' )
|
|
81 unless $role;
|
413
|
82
|
420
|
83 if ( isarray($role) ) {
|
|
84 my $tempRole = "unnamed-" . $nextRoleId++;
|
|
85 $this->roles->AddRole( $tempRole, $role );
|
|
86 $role = $tempRole;
|
|
87 }
|
413
|
88
|
420
|
89 $this->roles->GetLinearRoleHash($role);
|
413
|
90 }
|
|
91
|
|
92 sub Resolve {
|
420
|
93 my ( $this, $role, %opts ) = @_;
|
413
|
94
|
420
|
95 my $descriptor = $this->services->Resolve($role);
|
413
|
96
|
420
|
97 return $descriptor->Activate( ActivationContext->new($this) )
|
|
98 if $descriptor;
|
413
|
99
|
420
|
100 return $opts{default} if exists $opts{default};
|
413
|
101 }
|
|
102
|
|
103 sub ResolveAll {
|
420
|
104 my ( $this, $role, %opts ) = @_;
|
413
|
105
|
420
|
106 my $all = $this->services->ResolveAll($role);
|
413
|
107
|
420
|
108 my $context;
|
413
|
109
|
420
|
110 my @result;
|
413
|
111
|
420
|
112 foreach my $service (@$all) {
|
|
113 $context = ActivationContext->new($this)
|
421
|
114 unless $context && $opts{shared};
|
413
|
115
|
420
|
116 push @result, $service->Activate($context);
|
|
117 }
|
413
|
118
|
420
|
119 return \@result;
|
412
|
120 }
|
407
|
121
|
|
122 1;
|
|
123
|
|
124 __END__
|
|
125
|
|
126 =pod
|
|
127
|
|
128 =head1 NAME
|
|
129
|
|
130 C<IMPL::Config::Container> - dependency injection container
|
|
131
|
|
132 =head1 SYNOPSIS
|
|
133
|
|
134 =head2 METHODS
|
|
135
|
415
|
136 =head3 Resolve($role)
|
407
|
137
|
415
|
138 =head3 ResolveAll($role, shared => $useSharedContext)
|
407
|
139
|
415
|
140 =head3 Register($role, $service)
|
407
|
141
|
412
|
142 =cut
|