python-dependency-injector/docs/providers/factory.rst

108 lines
3.7 KiB
ReStructuredText

Factory providers
-----------------
.. currentmodule:: dependency_injector.providers
:py:class:`Factory` provider creates new instance of specified class on every
call.
Nothing could be better than brief example:
.. image:: /images/providers/factory.png
:width: 80%
:align: center
.. literalinclude:: ../../examples/providers/factory.py
:language: python
:linenos:
Factory providers and __init__ injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:py:class:`Factory` takes a various number of positional and keyword arguments
that are used as ``__init__()`` injections. Every time, when
:py:class:`Factory` creates new one instance, positional and keyword
argument injections would be passed as an instance's arguments.
Injections are done according to the next rules:
+ All providers (instances of :py:class:`Provider`) are called every time
when injection needs to be done.
+ Providers could be injected "as is" (delegated), if it is defined obviously.
Check out :ref:`factory_providers_delegation`.
+ All other injectable values are provided *"as is"*.
+ Positional context arguments will be appended after :py:class:`Factory`
positional injections.
+ Keyword context arguments have priority on :py:class:`Factory` keyword
injections and will be merged over them.
For example, if injectable value of injection is a :py:class:`Factory`, it
will provide new one instance (as a result of its call) every time, when
injection needs to be done.
Example below is a little bit more complicated. It shows how to create
:py:class:`Factory` of particular class with ``__init__()`` injections which
injectable values are also provided by another factories:
.. image:: /images/providers/factory_init_injections.png
.. literalinclude:: ../../examples/providers/factory_init_injections.py
:language: python
:linenos:
.. _factory_providers_delegation:
Factory providers delegation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:py:class:`Factory` provider could be delegated to any other provider via any
kind of injection.
As it was mentioned earlier, if :py:class:`Factory` is
injectable value, it will be called every time when injection needs to be
done. But sometimes there is a need to inject :py:class:`Factory` provider
itself (not a result of its call) as a dependency. Such injections are called
- *delegated provider injections*.
Saying in other words, delegation of factories - is a way to inject factories
themselves, instead of results of their calls.
:py:class:`Factory` delegation is performed by wrapping delegated
:py:class:`Factory` into special provider type - :py:class:`Delegate`, that
just returns wrapped :py:class:`Factory`.
Actually, there are three ways for creating factory delegates:
+ ``DelegatedFactory(...)`` - use special type of factory -
:py:class:`DelegatedFactory`. Such factories are always injected as
delegates ("as is").
+ ``Delegate(Factory(...))`` - obviously wrapping factory into
:py:class:`Delegate` provider.
+ ``Factory(...).delegate()`` - calling factory :py:meth:`Factory.delegate`
method, that returns delegate wrapper for current factory.
Example:
.. image:: /images/providers/factory_delegation.png
:width: 85%
:align: center
.. literalinclude:: ../../examples/providers/factory_delegation.py
:language: python
:linenos:
.. _factory_providers_specialization:
Factory providers specialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:py:class:`Factory` provider could be specialized for any kind of needs via
creating its subclasses.
One of such specialization features is a limitation to :py:class:`Factory`
provided type:
.. literalinclude:: ../../examples/providers/factory_provided_type.py
:language: python
:linenos: