Injecting provided object attributes, items, or call its methodsΒΆ

You can inject provided object attribute, item or result of its method call.

from dependency_injector import containers, providers


class Service:
    def __init__(self):
        self.value = 'foo'
        self.values = [self.value]

    def get_value(self):
        return self.value

    def __getitem__(self, item):
        return self.values[item]


class Client:
    def __init__(self, value1, value2, value3, value4):
        self.value1 = value1
        self.value2 = value2
        self.value3 = value3
        self.value4 = value4


class Container(containers.DeclarativeContainer):

    service = providers.Singleton(Service)

    client_factory = providers.Factory(
        Client,
        value1=service.provided[0],
        value2=service.provided.value,
        value3=service.provided.values[0],
        value4=service.provided.get_value.call(),
    )


if __name__ == '__main__':
    container = Container()

    client = container.client_factory()
    assert client.value1 == client.value2 == client.value3 == 'foo'

To use the feature you should use the .provided attribute of the injected provider. This attribute helps to specify what happens with the provided instance before the injection. You can use any combination of the following:

  • an attribute of the provided object
  • an item of the provided object
  • a call of the provided object method

When you use a call of the provided instance method you can specify the injections for this method like you do with any other provider.

You can do nested constructions:

from dependency_injector import containers, providers


class Service:

    def __init__(self, value):
        self.value = value

    def get_value(self):
        return self.value


class Container(containers.DeclarativeContainer):

    service = providers.Singleton(Service, value=42)

    dependency = providers.Object(
        {
            'foo': {
                'bar': 10,
                'baz': lambda arg: {'arg': arg}
            },
        },
    )

    demo_list = providers.List(
        dependency.provided['foo']['bar'],
        dependency.provided['foo']['baz'].call(22)['arg'],
        dependency.provided['foo']['baz'].call(service)['arg'],
        dependency.provided['foo']['baz'].call(service)['arg'].value,
        dependency.provided['foo']['baz'].call(service)['arg'].get_value.call(),
    )


if __name__ == '__main__':
    container = Container()

    assert container.demo_list() == [
        10,
        22,
        container.service(),
        42,
        42,
    ]

The .provided attribute is available for the next providers:

When you create a new provider subclass and want to implement the .provided attribute, you should use the ProvidedInstance provider. Add the .provided property implementation to a new subclass:

@property
def provided(self):
    return ProvidedInstance(self)