line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package MooseX::DIC::ServiceFactory::Moose; |
2
|
|
|
|
|
|
|
|
3
|
4
|
|
|
4
|
|
1835
|
use Moose; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
27
|
|
4
|
|
|
|
|
|
|
with 'MooseX::DIC::ServiceFactory'; |
5
|
4
|
|
|
4
|
|
23058
|
use namespace::autoclean; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
34
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
with 'MooseX::DIC::Loggable'; |
8
|
|
|
|
|
|
|
|
9
|
4
|
|
|
4
|
|
285
|
use aliased 'MooseX::DIC::UnregisteredServiceException'; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
32
|
|
10
|
4
|
|
|
4
|
|
673
|
use aliased 'MooseX::DIC::ContainerConfigurationException'; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
17
|
|
11
|
4
|
|
|
4
|
|
568
|
use aliased 'MooseX::DIC::ServiceCreationException'; |
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
16
|
|
12
|
4
|
|
|
4
|
|
362
|
use Try::Tiny; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
1640
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
has container => ( is => 'ro', does => 'MooseX::DIC::Container', required => 1 ); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub build_service { |
17
|
20
|
|
|
20
|
0
|
50
|
my ( $self, $service_meta ) = @_; |
18
|
|
|
|
|
|
|
|
19
|
20
|
|
|
|
|
63
|
my %dependencies = $self->build_dependencies_for($service_meta); |
20
|
|
|
|
|
|
|
|
21
|
19
|
|
|
|
|
35
|
my $service; |
22
|
|
|
|
|
|
|
try { |
23
|
19
|
|
|
19
|
|
1385
|
$service = $service_meta->class_name->new(%dependencies); |
24
|
|
|
|
|
|
|
} catch { |
25
|
0
|
|
|
0
|
|
0
|
MooseX::DIC::ServiceCreationException->throw( |
26
|
|
|
|
|
|
|
message => "Error while building an injected service: $_" ); |
27
|
19
|
|
|
|
|
149
|
}; |
28
|
|
|
|
|
|
|
|
29
|
19
|
|
|
|
|
7643
|
return $service; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub build_dependencies_for { |
33
|
20
|
|
|
20
|
0
|
38
|
my ($self,$service_meta) = @_; |
34
|
|
|
|
|
|
|
|
35
|
20
|
|
|
|
|
623
|
my $class_meta = $service_meta->class_name->meta; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# Build the to-be-injected dependencies of |
38
|
|
|
|
|
|
|
# the object |
39
|
20
|
|
|
|
|
405
|
my %dependencies = (); |
40
|
|
|
|
|
|
|
|
41
|
20
|
|
|
|
|
39
|
while(my ($name,$dependency) = each(%{$service_meta->dependencies})) { |
|
25
|
|
|
|
|
818
|
|
42
|
6
|
|
|
|
|
244
|
my $attribute = $class_meta->get_attribute($dependency->name); |
43
|
6
|
|
|
|
|
252
|
my $service_type = $attribute->type_constraint->name; |
44
|
|
|
|
|
|
|
|
45
|
6
|
50
|
|
|
|
432
|
if($self->container->has_service($service_type)) { |
46
|
|
|
|
|
|
|
|
47
|
6
|
100
|
|
|
|
212
|
if( $dependency->scope eq 'object' ) { |
|
|
50
|
|
|
|
|
|
48
|
3
|
|
|
|
|
93
|
$dependencies{ $dependency->name } = $self->container->get_service($service_type); |
49
|
|
|
|
|
|
|
} elsif( $dependency->scope eq 'request') { |
50
|
|
|
|
|
|
|
# It is a configuration error to ask for a request-injection of |
51
|
|
|
|
|
|
|
# a singleton object. It may indicate a misconception or a config |
52
|
|
|
|
|
|
|
# typo. |
53
|
3
|
|
|
|
|
72
|
my $attribute_service_meta = $self->container->get_service_metadata($service_type); |
54
|
3
|
100
|
|
|
|
81
|
ContainerConfigurationException->throw( message => |
55
|
|
|
|
|
|
|
"A singleton-scoped service cannot be injected into a request-injected attribute" |
56
|
|
|
|
|
|
|
) if $attribute_service_meta->scope eq 'singleton'; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# Replace the getter with a custom proxy function |
59
|
2
|
|
|
|
|
12
|
$attribute->remove_accessors; |
60
|
|
|
|
|
|
|
$class_meta->add_method( |
61
|
|
|
|
|
|
|
$dependency->name, |
62
|
|
|
|
|
|
|
sub { |
63
|
4
|
|
|
4
|
|
17
|
my ( $object, $value ) = @_; |
|
|
|
|
4
|
|
|
|
|
|
|
|
4
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# This is only a setter. Trying to write is an error |
66
|
4
|
50
|
|
|
|
11
|
ContainerException->throw( message => |
67
|
|
|
|
|
|
|
"A request-injected service accessor is read-only, it cannot be used as a setter" |
68
|
|
|
|
|
|
|
) if $value; |
69
|
|
|
|
|
|
|
|
70
|
4
|
|
|
|
|
124
|
return $self->container->get_service($service_type); |
71
|
|
|
|
|
|
|
} |
72
|
2
|
|
|
|
|
345
|
); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# We must pass a valid attribute value in case the attribute is required. It will never |
75
|
|
|
|
|
|
|
# get used, though. |
76
|
2
|
100
|
|
|
|
146
|
if( $attribute->is_required) { |
77
|
1
|
|
|
|
|
30
|
$dependencies{ $dependency->name } = $self->container->get_service($service_type); |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
} else { |
80
|
0
|
|
|
|
|
0
|
ContainerConfigurationException->throw( message => "Injection scope of dependencies can only |
81
|
|
|
|
|
|
|
be of type 'request' or 'object'" ); |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
} else { |
84
|
0
|
0
|
|
|
|
0
|
UnregisteredServiceException->throw(service => $service_type ) |
85
|
|
|
|
|
|
|
if ( $attribute->is_required ); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
19
|
|
|
|
|
67
|
return %dependencies; |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
1; |