Writing of custom providersΒΆ

List of Dependency Injector providers could be widened with custom providers.

Below are some tips and recommendations that have to be met:

  1. Every custom provider has to extend base provider class - Provider.
  2. Cusom provider’s __init__() could be overriden, but parent’s initializer (Provider.__init__()) has to be called.
  3. Providing strategy has to be implemented in custom provider’s Provider.__call__() method.
  4. If custom provider is based on some standard providers, it is better to use delegation of standard providers, then extending of them.
  5. If custom provider defines any attributes, it is good to list them in __slots__ attribute (as Dependency Injector does). It can save some memory.
  6. If custom provider deals with injections, it is strongly recommended to be consistent with Factory, Singleton and Callable providers style.

Example:

../_images/custom_provider.png
 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
"""Custom `Factory` example."""

import dependency_injector.providers as providers


class User(object):
    """Example class User."""


class UsersFactory(providers.Provider):
    """Example users factory."""

    __slots__ = ('_factory',)

    def __init__(self):
        """Initializer."""
        self._factory = providers.Factory(User)
        super(UsersFactory, self).__init__()

    def __call__(self, *args, **kwargs):
        """Return provided object.

        Callable interface implementation.
        """
        if self.last_overriding is not None:
            return self.last_overriding._provide(args, kwargs)
        return self._factory(*args, **kwargs)


# Users factory:
users_factory = UsersFactory()

# Creating several User objects:
user1 = users_factory()
user2 = users_factory()

# Making some asserts:
assert isinstance(user1, User)
assert isinstance(user2, User)
assert user1 is not user2