Dynamic containersΒΆ

DynamicContainer is an inversion of control container with dynamic structure. It should cover most of the cases when list of providers that would be included in container is non-deterministic and depends on application’s flow or its configuration (container’s structure could be determined just after application will be started and will do some initial work, like parsing list of container’s providers from the configuration).

While DeclarativeContainer acts on class-level, DynamicContainer does the same on instance-level.

Here is an simple example of defining dynamic container with several factories:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
"""Dynamic container simple example."""

import dependency_injector.containers as containers
import dependency_injector.providers as providers


# Defining dynamic container:
container = containers.DynamicContainer()
container.factory1 = providers.Factory(object)
container.factory2 = providers.Factory(object)

# Creating some objects:
object1 = container.factory1()
object2 = container.factory2()

# Making some asserts:
assert object1 is not object2
assert isinstance(object1, object) and isinstance(object2, object)

Next example demonstrates creation of dynamic container based on some configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
"""Creation of dynamic container based on some configuration example."""

import collections

import dependency_injector.containers as containers


# Defining several example services:
UsersService = collections.namedtuple('UsersService', [])
AuthService = collections.namedtuple('AuthService', [])


def import_cls(cls_name):
    """Import class by its fully qualified name.

    In terms of current example it is just a small helper function. Please,
    don't use it in production approaches.
    """
    path_components = cls_name.split('.')
    module = __import__('.'.join(path_components[:-1]),
                        locals(),
                        globals(),
                        fromlist=path_components[-1:])
    return getattr(module, path_components[-1])


# "Parsing" some configuration:
config = {
    'services': {
        'users': {
            'class': '__main__.UsersService',
            'provider_class': 'dependency_injector.providers.Factory',
        },
        'auth': {
            'class': '__main__.AuthService',
            'provider_class': 'dependency_injector.providers.Factory',
        }
    }
}

# Creating empty container of service providers:
services = containers.DynamicContainer()

# Filling dynamic container with service providers using configuration:
for service_name, service_info in config['services'].iteritems():
    # Runtime importing of service and service provider classes:
    service_cls = import_cls(service_info['class'])
    service_provider_cls = import_cls(service_info['provider_class'])

    # Binding service provider to the dynamic service providers catalog:
    setattr(services, service_name, service_provider_cls(service_cls))

# Creating some objects:
users_service = services.users()
auth_service = services.auth()

# Making some asserts:
assert isinstance(users_service, UsersService)
assert isinstance(auth_service, AuthService)