Providers and resolving
Providers
Providers are a wrapper over the objects you plan to use in your application code. Providers are able to work with different objects, but for the same purpose - for resolving and assembling objects. At a minimum, there are the following reasons (and clear advantages) for introducing an abstraction such as a provider:
ability to distinguish ‘normal’ function parameters from providers in order to automatically inject arguments using the
@injectdecorator;object lifecycle management;
simple and ubiquitous reuse - instead of another object build with parameter injection, you just need to ask the provider to resolve the object to be wrapped, the provider will do it all by itself;
possibility of overriding/substitution of object parameters and the object itself for other objects (which is incredibly useful when writing tests);
declarative style of building complex objects with all the advantages of the above included.
Resolving
Resolving is the process of building and receiving a ready-to-use object from the provider. You can ask the provider to build and give you a ready-to-use object, you just need to tell the provider the rules for building it - usually a future object class or callable-object and positional and/or keyword arguments. Please refer to the documentation section with the available providers (transient, singeton and etc.)
Below is an example of a provider definition and a resolving object representing a container for storing some data:
from dataclasses import dataclass
from injection.providers.transient import Transient
@dataclass
class SomeDataclass:
int_value: int
some_string_value: str
if __name__ == '__main__':
provider = Transient(SomeDataclass, int_value=5, some_string_value='hello')
resolved_object = provider()
print(resolved_object)
>> .venv/bin/python3 example.py
SomeDataclass(int_value=5, some_string_value='hello')
Process finished with exit code 0