File Coverage

blib/lib/IOC/Service/ConstructorInjection.pm
Criterion Covered Total %
statement 54 56 96.4
branch 16 16 100.0
condition 11 15 73.3
subroutine 12 12 100.0
pod 2 2 100.0
total 95 101 94.0


line stmt bran cond sub pod time code
1              
2             package IOC::Service::ConstructorInjection;
3              
4 7     7   63239 use strict;
  7         15  
  7         239  
5 7     7   44 use warnings;
  7         12  
  7         286  
6              
7             our $VERSION = '0.07';
8              
9 7     7   38 use Scalar::Util qw(blessed);
  7         12  
  7         438  
10              
11 7     7   516 use IOC::Exceptions;
  7         13  
  7         339  
12              
13 7     7   63 use base 'IOC::Service';
  7         13  
  7         2405  
14              
15             sub new {
16 21     21 1 5768 my ($_class, $name, $component_class, $component_constructor, $parameters) = @_;
17 21   33     114 my $class = ref($_class) || $_class;
18 21         45 my $service = {};
19 21         61 bless($service, $class);
20 21         87 $service->_init($name, $component_class, $component_constructor, $parameters);
21 16         76 return $service;
22             }
23              
24             sub _init {
25 21     21   50 my ($self, $name, $component_class, $component_constructor, $parameters) = @_;
26 21 100 100     140 (defined($component_class) && defined($component_constructor))
27             || throw IOC::InsufficientArguments "You must provide a class and a constructor method";
28 19 100 100     123 (defined($parameters) && ref($parameters) eq 'ARRAY')
29             || throw IOC::InsufficientArguments "You must provide a set of parameters for the constructor as an Array reference";
30 16         74 $self->{component_class} = $component_class;
31 16         39 $self->{component_constructor} = $component_constructor;
32 16         39 $self->{parameters} = $parameters;
33             $self->SUPER::_init(
34             $name,
35             sub {
36             # get the IOC::Container object
37 19     19   35 my $c = shift;
38             # check if there is an entry in the
39             # symbol table for this class already
40             # (meaning it has been loaded) and if
41             # not, then require it
42 19 100   1   29 eval {
  1     1   1095  
  1         3  
  1         17  
  1         8458  
  0            
  0            
43 7     7   46 no strict 'refs';
  7         13  
  7         3664  
44             # check for the symbol table itself ...
45             (keys %{"${component_class}::"} ||
46             # and then to be sure, lets look for
47             # either the VERSION or the ISA variables
48             (defined ${"${component_class}::VERSION"}
49 19 100 66     30 || defined @{"${component_class}::ISA"})) ? 1 : 0;
50             } || eval "use $component_class";
51             # throw our exception if the class fails to load
52 19 100       86 throw IOC::ClassLoadingError "The class '$component_class' could not be loaded" => $@ if $@;
53             # check to see if the specified
54             # constructor is there
55 18         194 my $constructor = $component_class->can($component_constructor);
56             # if it is not, then throw our exception
57 18 100       64 (defined($constructor))
58             || throw IOC::ConstructorNotFound "The constructor '$component_constructor' could not be found for class '$component_class'";
59             # now take care of the parameters
60             # NOTE:
61             # we must be sure to copy this otherwise it
62             # will not work correctly with the prototype
63             # verisons, this has to do with the scope of
64             # this array, and how long it lives
65 17         29 my @parameters = @{$parameters};
  17         55  
66 17         59 for (my $i = 0; $i < scalar @parameters; $i++) {
67             # if the parameter is not been blessed
68             # into the pseudo-package ComponentParameter
69             # then we skip it, however ...
70 19 100 66     155 next unless blessed($parameters[$i]) && $parameters[$i]->isa("ComponentParameter");
71             # if it has been, then we derference it
72             # into the name of the service expected
73             # and use the IOC::Container to get an
74             # instance of that service and replace
75             # that in the parameters array
76 8 100       18 if (${$parameters[$i]} =~ /\//) {
  8         33  
77 2         4 $parameters[$i] = $c->find(${$parameters[$i]});
  2         9  
78             }
79             else {
80 6         9 $parameters[$i] = $c->get(${$parameters[$i]});
  6         35  
81             }
82             }
83             # now we have the class loaded,
84             # the constructor confirmed, and
85             # the parameters realized, so we
86             # can create the instance now
87 17         63 return $component_class->$constructor(@parameters);
88             }
89 16         171 );
90             }
91              
92             # class method
93 7     7 1 1784 sub ComponentParameter { shift; bless(\(my $param = shift), "ComponentParameter") };
  7         58  
94              
95             1;
96              
97             __END__