Provider<T>
Normally when injecting a dependency, one instance of the dependency is created before creating the depending object. This may not be ideal since the depending object might:
- Want multiple instance of the object, for example, populating an array.
- Have cyclic dependency at runtime
For every binding T
, Lockjaw also automatically creates a binding
to Provider<T>
, which creates a new
instance of T
everytime get()
is
called.
Since a Provider
needs to use the component to create the instance, its lifetime is bound by the
component.
Creating multiple instances
Provider<T>
can be used to create instances on request.
struct Foo {
bar_provider: Provider<Bar>,
bars : Vec<Bar>,
}
impl Foo{
#[inject]
pub fn new(bar_provider: Provider<Bar>) -> Foo {
bar_provider,
bars: vec![bar_provider.get(), bar_provider.get(), bar_provider.get()],
}
pub fn add_more_bar(&mut self){
self.bars.push(self.bar_provider.get())
}
}
Bypassing runtime cyclic dependency
Since regular dependencies must be created before instantiating an object, cyclic dependencies will result in a recursive stack overflow when the constructor is called. Lockjaw will detect this situation and refuse to compile your project.
However sometimes the dependency is only used at runtime, not at object construction. This is
especially common when singleton classes need to refer to each other. By using
Provider<T>
the cycle can be broken.
struct Foo<'component> {
bar_provider: Provider<'component, Box<Bar<'component>>>,
}
#[injectable]
impl<'component> Foo<'component> {
#[inject]
pub fn new(bar: Provider<'component, Box<Bar<'component>>>) -> Foo<'component> {
Self { bar_provider: bar }
}
pub fn create_bar(&self) -> Box<Bar<'component>> {
self.bar_provider.get()
}
}
struct Bar<'component> {
foo: Box<Foo<'component>>,
}
#[injectable]
impl<'component> Bar<'component> {
#[inject]
pub fn new(foo: Box<Foo<'component>>) -> Bar<'component> {
Self { foo }
}
}
In this example, while instantiating Bar
, instantiates a Foo
, Bar
won't be created
until Foo.create_bar()
is called, hence creating either won't trigger a stack overflow.
Trying to call Provider.get
may still lead to a stack overflow, and Lockjaw cannot check this for
you.