NAME

Beam::Wire - A Dependency Injection Container

SYNOPSIS

# wire.yml
dbh:
    class: 'DBI'
    method: connect
    args:
        - 'dbi:mysql:dbname'
        - {
            PrintError: 1
          }
cache:
    class: 'CHI'
    args:
        driver: 'DBI'
        dbh: { ref: 'dbh' }

# myscript.pl
use Beam::Wire;
my $wire  = Beam::Wire->new( file => 'wire.yml' );
my $dbh   = $wire->get( 'dbh' );
my $cache = $wire->get( 'cache' );

$wire->set( 'dbh', DBI->new( 'dbi:pgsql:dbname' ) );

DESCRIPTION

Beam::Wire is a dependency injection container.

TODO: Explain what a DI container does and why you want it

ATTRIBUTES

file

Read the list of services from the given file. The file is described below in the FILE section.

dir

A directory to use when searching for inner container files. Defaults to the directory that contains the file.

config

A hashref of service configurations. This is normally filled in by reading the FILE.

services

A hashref of services. If you have any services already built, add them here.

METHODS

new

Create a new container.

FILE

Beam::Wire can read a YAML file to fill a container with services. The file should be a single hashref. The keys will be the service names.

SERVICE ATTRIBUTES

class

The class to instantiate. The class will be loaded and the method (below) method called.

method

The class method to call to construct the object. Defaults to new.

args

The arguments to the method method. This can be either an array or a hash, like so:

# array
dbh: 
    class: DBI
    method: connect
    args:
        - 'dbi:mysql:dbname'

# hash
cache:
    class: CHI
    args:
        driver: Memory
        max_size: 16MB

Using the array of arguments, you can give arrayrefs or hashrefs:

# arrayref of arrayrefs
names:
    class: 'Set::CrossProduct'
    args:
        -
            - [ 'Foo', 'Barkowictz' ]
            - [ 'Bar', 'Foosmith' ]
            - [ 'Baz', 'Bazleton' ]

# hashref
cache:
    class: CHI
    args:
        -   driver: Memory
            max_size: 16MB

INNER CONTAINERS

Beam::Wire objects can hold other Beam::Wire objects!

inner:
    class: Beam::Wire
    args:
        config:
            dbh:
                class: DBI
                method: connect
                args:
                    - 'dbi:mysql:dbname'
            cache:
                class: CHI
                args:
                    driver: Memory
                    max_size: 16MB

Inner containers' contents can be reached from outer containers by separating the names with a slash character:

my $dbh = $wire->get( 'inner/dbh' );

INNER FILES

inner:
    class: Beam::Wire
    args:
        file: inner.yml

Inner containers can be created by reading files just like the main container. If the file attribute is relative, the parent's dir attribute will be added:

# share/parent.yml
inner:
    class: Beam::Wire
    args:
        file: inner.yml

# share/inner.yml
dbh:
    class: DBI
    method: connect
    args:
        - 'dbi:sqlite:data.db'

# myscript.pl
use Beam::Wire;
my $container = Beam::Wire->new(
    file => 'share/parent.yml',
);
my $dbh = $container->get( 'inner/dbh' );

If more control is needed, you can set the dir attribute on the parent container.

If even more control is needed, you can make a subclass of Beam::Wire.