Simple Injection
Finally, dependency injection (DI).
We want our greeting to have punctuation at the end, such as a period or, in the U.S., !!!
because we Americans are like puppies.
Everything is the same as in Decorators, Simple Case, we just have different models:
# models.py
from dataclasses import dataclass
from wired.dataclasses import factory
@factory()
@dataclass
class Settings:
"""Store some configuration settings for the app"""
punctuation: str = '.'
@factory()
@dataclass
class Greeter:
settings: Settings # Ask DI to get the configured Settings
name: str = 'Mary'
def __call__(self, customer):
punctuation = self.settings.punctuation
return f'Hello {customer} my name is {self.name}{punctuation}'
We register a dataclass
Settings
with one field, defaulted to a value of a periodGreeter
now asks DI to assign the configuredSettings
to a field……which is then used in the
__call__
So this is DI. What’s actually happening?
wired.dataclasses
creates your dataclass instance. When it does, it looks at each field’s type annotation. It uses this type to look in the registry for that configured type, then calls the factory to get an instance. Which it then stores on the field.
This is already useful and powerful. The “callee” and the “caller” have something in between – DI – which can help decouple calling. The callee – the dataclass – can provide instructions for what it wants provided – hence the “inversion of control” expression. Here we are using dataclassses
and its field
construct as a DSL for object construction.
There’s a lot more to this, as we’ll see in the following sections.
To finish, we change our assert
to add the period:
# Application starts up
app = App()
app.scan()
# Later, a request comes in
result = process_request(app.registry)
assert 'Hello Larry my name is Mary.' == result