#!/usr/local/bin/perl #!/usr/bin/perl use strict; use warnings; my $dependency = { # id 'sample1' => { # component name 'Display' => { 'factory' => 'Display', }, }, 'sample2' => { 'Display' => { 'factory' => 'Display', 'prop' => { 'filter' => 'Filter', }, }, 'Filter' => { 'factory' => 'Filter', }, }, 'sample3' => { 'Display' => { 'factory' => 'Display', 'prop' => { 'filter' => 'Filter', }, }, 'Filter' => { 'factory' => 'LabelFilter', 'prop' => { 'label' => {'value' => 'test'}, }, }, }, }; print "A Very Simple Dependency Injection Demo.\n"; my $registry = DIContainer->new($dependency); for my $id (sort keys %$dependency) { print "demo $id => "; my $display = $registry->component($id, 'Display'); $display->puts("a" .. "g", "\n"); } exit; package IComponent; sub create_instance { my($class, @arg) = @_; return $class->new(@arg); } sub property { my($self, $f, @arg) = @_; if (@arg) { $self->{$f} = $arg[0]; } return $self->{$f}; } package Display; use base qw(IComponent); sub new { my($class) = @_; return bless {}, $class; } sub filter { return shift->property('filter', @_) } sub puts { my($self, @arg) = @_; if (eval{ $self->filter->can('run') }) { print $self->filter->run(@arg); } else { print @arg; } return; } package Filter; use base qw(IComponent); sub new { my($class) = @_; return bless {}, $class; } sub run { my($self, @arg) = @_; return join q{ }, @arg; } package LabelFilter; use base qw(Filter); sub label { shift->property('label', @_) } sub run { my($self, @arg) = @_; return $self->SUPER::run($self->label, q{:}, @arg); } package DIContainer; use Carp; sub new { my($class, @arg) = @_; my %self = @arg == 1 && ref $arg[0] eq 'HASH' ? %{$arg[0]} : @arg; return bless \%self, $class; } sub component { my($self, $id, $name) = @_; my $dependency = $self->{$id}{$name} or croak "not registered component $id > $name."; my $factory = $dependency->{factory}; UNIVERSAL::can($factory, 'create_instance') or croak "package $factory cannot create instance for $id > $name."; my $instance = $factory->create_instance; while (my($prop, $v) = each %{$dependency->{prop}}) { eval{ $instance->can($prop) } or croak "package $factory cannot $prop for $id > $name."; unless (ref $v) { $instance->property($prop, $self->component($id, $v)); } elsif (ref $v eq 'HASH') { $instance->property($prop, $v->{value}); } } return $instance; }