Factories¶
If constructing your component is expensive and you only want to instantiate it if it’s really necessary you can add a factory function to the injector which will only be called when the component is needed.
When registering a factory function, make sure the return type annotation matches the type of the component you want to inject.
Demonstration:
import time
from component_injector import Injector
injector = Injector()
class CheapComponent:
pass
class ExpensiveComponent:
pass
def expensive_factory() -> ExpensiveComponent:
time.sleep(1)
return ExpensiveComponent()
injector.register(CheapComponent())
injector.register_factory(expensive_factory)
@injector.inject
def consumer_1(c1: CheapComponent):
pass
@injector.inject
def consumer_2(c1: CheapComponent, c2: ExpensiveComponent):
pass
# This will not create the expensive components.
consumer_1()
# ExpensiveComponent will not be instantiated until needed.
consumer_2()
# Needing it again will use the same instance created before.
consumer_2()
Asynchronous factories¶
If you register a factory that returns an Awaitable, you can use it to inject the resolved component into a coroutine:
import asyncio
from component_injector import Injector
class Component:
pass
async def factory() -> Component:
await asyncio.sleep(1)
return Component()
injector = Injector()
injector.register_factory(factory)
@injector.inject
async def consumer(c: Component):
pass
loop = asyncio.get_event_loop()
loop.run_until_complete(consumer())