Rewire - Dependency Injection
Dependency Injection Container for Perl 5
use Rewire;
my $services = {
filetemp => {
package => 'File/Temp'
},
tempfile => {
package => 'Mojo/File',
argument => { '$service' => 'filetemp' }
}
};
my $rewire = Rewire->new(services => $services);
$rewire->resolve('tempfile');
This package provides methods for using dependency injection, and building objects and values.
This package integrates behaviors from:
This package uses type constraints from:
This package supports the following scenarios:
use Rewire;
my $services = {
io => {
package => 'IO/Handle'
},
log => {
package => 'Mojo/Log',
argument => {
format => { '$callback' => 'io' }
}
},
};
my $rewire = Rewire->new(
services => $services
);
This package supports resolving services as callbacks to be passed around
and/or resolved by other services. The $callback
directive is used to
specify the name of a service to be resolved and passed as an argument.
use Rewire;
my $services = {
file => {
package => 'Mojo/File',
argument => { '$envvar' => 'home' }
}
};
my $rewire = Rewire->new(
services => $services
);
This package supports inlining environment variables as arguments to services.
The $envvar
directive is used to specify the name of an environment
variable, and can also be used in metadata for reusability.
use Rewire;
my $services = {
temp => {
package => 'File/Temp'
},
file => {
package => 'Mojo/File',
argument => { '$function' => 'temp#tempfile' }
}
};
my $rewire = Rewire->new(
services => $services
);
This package supports inlining the result of a service resolution and function
call as arguments to services. The #
delimited $function
directive is
used to specify the name of an existing service on the right-hand side, and an
arbitrary function to be call on the result on the left-hand side.
use Rewire;
my $metadata = {
home => '/home/ubuntu'
};
my $services = {
file => {
package => 'Mojo/File',
argument => { '$metadata' => 'home' }
}
};
my $rewire = Rewire->new(
metadata => $metadata,
services => $services
);
This package supports inlining configuration data as arguments to services.
The $metadata
directive is used to specify the name of a stashed
configuration value or data structure.
use Rewire;
my $services = {
temp => {
package => 'File/Temp'
},
file => {
package => 'Mojo/File',
argument => { '$method' => 'temp#filename' }
}
};
my $rewire = Rewire->new(
services => $services
);
This package supports inlining the result of a service resolution and method
call as arguments to services. The #
delimited $method
directive is used
to specify the name of an existing service on the right-hand side, and an
arbitrary method to be call on the result on the left-hand side.
use Rewire;
my $services = {
temp => {
package => 'File/Temp'
},
file => {
package => 'Mojo/File',
argument => { '$routine' => 'temp#tempfile' }
}
};
my $rewire = Rewire->new(
services => $services
);
This package supports inlining the result of a service resolution and routine
call as arguments to services. The #
delimited $routine
directive is
used to specify the name of an existing service on the right-hand side, and an
arbitrary routine to be call on the result on the left-hand side.
use Rewire;
my $services = {
io => {
package => 'IO/Handle'
},
log => {
package => 'Mojo/Log',
argument => {
handle => { '$service' => 'io' }
}
},
};
my $rewire = Rewire->new(
services => $services
);
This package supports inlining resolved services as arguments to other
services. The $service
directive is used to specify the name of a service
to be resolved and passed as an argument.
use Rewire;
my $metadata = {
applog => '/var/log/rewire.log'
};
my $services = {
mojo_log => {
package => 'Mojo/Log',
argument => {
path => { '$metadata' => 'applog' },
level => 'warn'
},
argument_as => 'list'
}
};
my $rewire = Rewire->new(
services => $services,
metadata => $metadata
);
This package supports providing static and/or dynamic arguments during object
construction from metadata
or other services
.
use Rewire;
my $services = {
mojo_date => {
package => 'Mojo/Date',
builder => [
{
method => 'new',
return => 'self'
},
{
method => 'to_datetime',
return => 'result'
}
]
}
};
my $rewire = Rewire->new(
services => $services,
);
This package supports specifying multiple build steps as function
,
method
, and routine
calls and chaining them together.
use Rewire;
my $metadata = {
home => '/home/ubuntu'
};
my $services = {
tempfile => {
package => 'Mojo/File',
argument => { '$metadata' => 'home' }
}
};
my $rewire = Rewire->new(
services => $services,
metadata => $metadata
);
This package supports configuring services and metadata in the service of building objects and values.
use Rewire;
my $services = {
mojo_date => {
package => 'Mojo/Date',
constructor => 'new'
}
};
my $rewire = Rewire->new(
services => $services
);
This package supports specifying constructors other than the traditional new
routine. A constructor is always called with the package name as the invocant.
use Rewire;
my $services = {
io => {
package => 'IO/Handle'
},
log => {
package => 'Mojo/Log',
argument => {
handle => { '$service' => 'io' }
}
},
development_log => {
package => 'Mojo/Log',
extends => 'log',
builder => [
{
method => 'new',
return => 'self'
},
{
method => 'path',
argument => '/tmp/development.log',
return => 'none'
},
{
method => 'level',
argument => 'debug',
return => 'none'
}
]
},
production_log => {
package => 'Mojo/Log',
extends => 'log',
builder => [
{
method => 'new',
return => 'self'
},
{
method => 'path',
argument => '/tmp/production.log',
return => 'none'
},
{
method => 'level',
argument => 'warn',
return => 'none'
}
]
},
staging_log => {
package => 'Mojo/Log',
extends => 'development_log',
},
testing_log => {
package => 'Mojo/Log',
extends => 'log',
},
};
my $rewire = Rewire->new(
services => $services
);
This package supports extending services in the definition of other services, recursively compiling service configurations and eventually executing the requested compiled service.
use Rewire;
my $services = {
foo_sum => {
package => 'Mojo/Util',
function => 'md5_sum',
argument => 'foo',
}
};
my $rewire = Rewire->new(
services => $services,
);
This package supports specifying construction as a function call, which when called does not provide an invocant.
use Rewire;
my $metadata = {
home => '/home/ubuntu'
};
my $services = {
tempfile => {
package => 'Mojo/File',
argument => { '$metadata' => 'home' },
lifecycle => 'singleton'
}
};
my $rewire = Rewire->new(
services => $services,
metadata => $metadata
);
This package supports different lifecycle options which determine when services are built and whether they're persisted.
use Rewire;
my $metadata = {
homedir => '/home',
tempdir => '/tmp'
};
my $services = {
home => {
package => 'Mojo/Path',
argument => { '$metadata' => 'homedir' },
},
temp => {
package => 'Mojo/Path',
argument => { '$metadata' => 'tempdir' },
}
};
my $rewire = Rewire->new(
services => $services,
metadata => $metadata
);
This package supports specifying data and structures which can be used in the construction of multiple services.
use Rewire;
my $services = {
mojo_url => {
package => 'Mojo/URL',
argument => 'https://perl.org',
method => 'new'
}
};
my $rewire = Rewire->new(
services => $services,
);
This package supports specifying construction as a method call, which when called provides the package or object instance as the invocant.
use Rewire;
my $services = {
home => {
package => 'Mojo/Path',
argument => '/home',
},
temp => {
package => 'Mojo/Path',
argument => '/tmp',
}
};
my $rewire = Rewire->new(
services => $services
);
# resolve services via method calls
[
$rewire->home, # i.e. $rewire->process('home')
$rewire->temp # i.e. $rewire->process('temp')
]
This package supports the resolution of services using a single method call. This is enabled by intercepting method calls and proxying them to the "process" method.
use Rewire;
my $services = {
mojo_url => {
package => 'Mojo/URL',
argument => 'https://perl.org',
routine => 'new'
}
};
my $rewire = Rewire->new(
services => $services,
);
This package supports specifying construction as a function call, which when called provides the package as the invocant.
my $metadata = {
home => '/home/ubuntu'
};
my $services = {
tempfile => {
package => 'Mojo/File',
argument => { '$metadata' => 'home' },
lifecycle => 'eager'
}
};
my $rewire = Rewire->new(
services => $services,
metadata => $metadata
);
This package supports defining services to be constructed on-demand or automatically on instantiation.
This package has the following attributes:
context(CodeRef)
This attribute is read-only, accepts (CodeRef)
values, and is optional.
engine(InstanceOf["Data::Object::Space"])
This attribute is read-only, accepts (InstanceOf["Data::Object::Space"])
values, and is optional.
metadata(HashRef)
This attribute is read-only, accepts (HashRef)
values, and is optional.
services(HashRef)
This attribute is read-only, accepts (HashRef)
values, and is optional.
This package implements the following methods:
config() : HashRef
The config method returns the configuration based on the services
and
metadata
attributes.
-
config example #1
# given: synopsis $rewire->config;
process(Str $name, Any $argument, Maybe[Str] $argument_as) : Any
The process method processes and returns an object or value based on the service named but where the arguments are provided ad-hoc. Note: This method is meant to be used to construct services ad-hoc and as such bypasses caching and lifecycle effects.
-
process example #1
# given: synopsis $rewire->process('tempfile', 'rewire.tmp');
-
process example #2
use Rewire; my $metadata = { logfile => '/var/log/rewire.log', }; my $services = { mojo_log => { package => 'Mojo/Log', argument => { '$metadata' => 'logfile' }, } }; my $rewire = Rewire->new( services => $services, metadata => $metadata ); $rewire->process('mojo_log', { level => 'fatal', path => { '$metadata' => 'logfile' } });
-
process example #3
use Rewire; my $metadata = { logfile => '/var/log/rewire.log', }; my $services = { mojo_log => { package => 'Mojo/Log', builder => [ { method => 'new', return => 'self' } ] } }; my $rewire = Rewire->new( services => $services, metadata => $metadata ); $rewire->process('mojo_log', { level => 'fatal', path => { '$metadata' => 'logfile' } });
resolve(Str $name) : Any
The resolve method resolves and returns an object or value based on the service named. Note: This method is recommended to be used to construct services as defined by the configuration and as such doesn't not allow passing additional arguments.
-
resolve example #1
# given: synopsis $rewire->resolve('tempfile');
-
resolve example #2
use Rewire; my $services = { mojo_log => { package => 'Mojo/Log', argument => { level => 'fatal', path => '/var/log/rewire.log' }, } }; my $rewire = Rewire->new( services => $services, ); $rewire->resolve('mojo_log');
-
resolve example #3
package Dynamic; sub import; sub AUTOLOAD { bless {}; } sub DESTROY { ; # noop } package main; use Rewire; my $services = { dynamic => { package => 'Dynamic', builder => [ { method => 'new', return => 'self' }, { method => 'missing_method', return => 'result' } ], } }; my $rewire = Rewire->new( services => $services, ); $rewire->resolve('dynamic');
validate() : Object
The validate method validates the configuration and throws an exception if invalid, otherwise returns itself.
-
validate example #1
# given: synopsis $rewire->validate;
Al Newkirk, [email protected]
Copyright (C) 2011-2019, Al Newkirk, et al.
This is free software; you can redistribute it and/or modify it under the terms of the The Apache License, Version 2.0, as elucidated in the "license file".