Dependency Injection (DI) is a powerful design pattern used to achieve Inversion of Control (IoC) between classes and their dependencies. Within the context of our voice assistant, Dependency Injection facilitates the provision of specific objects or values to command functions. This ensures that these functions can readily access external resources or other system components.
This guide provides an overview of the Dependency Injection implementation, how to utilize it in your voice assistant, and some native dependencies.
There are two response handlers:
ResponseHandler. They oversee the processing of responses, asynchronously and synchronously, respectively. To employ them, simply include the required type (class) annotation as an argument within the function declaration. The argument's name isn't significant for this dependency.
In the showcased example, the
AsyncResponseHandler is automatically injected into the
foo command function upon its invocation.
inject_dependency method serves to integrate specific dependencies into a function. This method determines the function's dependencies and subsequently calls it. Contrary to the response handler, this dependency is identified by the argument's name.
foo dependency is injected and executed within the
bar command function.
Accessing DIContainer in a Command¶
CommandsContext class initializes with a
dependency_manager of the
DependencyManager type. This manager undertakes the role of identifying and injecting the requisite dependencies for command functions.
To tap into the DIContainer inside a command, simply declare the needed dependency as a command function parameter. The
DependencyManager will resolve this parameter and supply the appropriate object or value.
For more advanced access, you can extract the container as a dependency of type
DIContainer, as demonstrated:
This is feasible because the default DI container internally registers itself as a dependency:
Adding Custom Dependency¶
You can incorporate custom dependencies using the
add_dependency method of the default shared instance of
In this instance, a new dependency named
CustomType, with the value
custom_value is appended. If the name is set to
None, you can later choose any name for the function argument; the dependency will be discerned solely by type (like
AsyncResponseHandler). Conversely, setting the type to
None allows the dependency to be detected purely by the argument name (like
Creating a Custom Container¶
To employ a custom container for Dependency Injection in lieu of the default one, instantiate a new
DependencyManager and input your custom dependencies. This tailored container can subsequently be utilized during the
It's worth noting that the CommandsContext always registers several native dependencies upon initialization:
However, other native dependencies will be absent in the custom container unless you manually incorporate them.
The adaptability provided by the Dependency Injection framework ensures your command functions remain modular, simplifying testing. As you further develop your voice assistant, utilize this system to adeptly handle your dependencies.