# 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](http://search.cpan.org/perldoc?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](http://search.cpan.org/perldoc?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](http://search.cpan.org/perldoc?dir) attribute on the parent container.

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