Attribute Macro lockjaw::subcomponent [−][src]
#[subcomponent]
Expand description
Annotates a trait that composes a sub-dependency graph, which has additional bindings/scoped
bindings, and can also access bindings from the parent #[component]
/
#[subcomponent]
.
#[subcomponent]
can be seen as some sort of “session”. For example a web server can have a
#[component]
for global helpers, and creates a #[subcomponent]
for each request using the URL.
Bindings within the #[subcomponent]
can depend on the URL and other bindings derived from it, or
have a scoped shared object for the same request, while being isolated from other requests.
Operations on a #[subcomponent]
is almost identical to a #[component]
(crate::component), other
than it’s extended dependency graph and creation of the #[subcomponent]
A subcomponent cannot outlive its parent component.
struct SubcomponentModule {}
#[module]
impl SubcomponentModule {
#[provides]
pub fn provide_i32() -> i32 {
32
}
}
#[subcomponent(modules: [SubcomponentModule])]
pub trait MySubcomponent<'a> {
fn fi64(&self) -> i64;
fn fi32(&self) -> i32;
}
struct ParentComponentModule {}
#[module(subcomponents: [MySubcomponent])]
impl ParentComponentModule {
#[provides]
pub fn provide_i64() -> i64 {
64
}
}
#[component(modules: [ParentComponentModule])]
pub trait MyComponent {
fn sub(&self) -> Cl<dyn MySubcomponentBuilder>;
}
pub fn main() {
let component: Box<dyn MyComponent> = <dyn MyComponent>::new();
let sub: Cl<dyn MySubcomponent> = component.sub().build();
// bindings in the subcomponent.
assert_eq!(sub.fi32(), 32);
// bindings in the parent component is still accessible.
assert_eq!(sub.fi64(), 64);
}
lockjaw::epilogue!();
Installing a subcomponent
A subcomponent can be installed to a parent component by specifying
the subcomponents
metadata in a #[module]
, and adding the module to the
parent component.
Once installed, the subcomponent builder binding will be provided to the parent component, which can be used to create a subcomponent instance.
Subcomponent builder
For a Foo
subcomponent, instead of adding a static build
method to the trait, lockjaw generates
a new builder trait in the same mod:
[subcomponent visibility] trait FooBuilder<'parent_component> {
fn build(&self, modules: BUILDER_MODULES) -> Box<dyn Foo>
}
If the builder_modules
metadata is not provided, the modules
parameter will be omitted, and the
signature becomes pub fn build(&self) -> Box<dyn Foo>
Calling build()
creates a new instance of the subcomponent.
FooBuilder
is injectable in components where it is installed in the
form of Cl<dyn FooBuilder>
.
A subcomponent builder cannot outlive its parent component.
Metadata
modules
parent
Path to a #[define_component]
/#[define_subcomponent]
trait to specify the parent of this subcomponent. The subcomponent will have access to the parent’s
bindings, and the subcomponent builder will be bound in the parent component.
If the parent is a #[component]
/#[subcomponent]
, the
subcomponents
metadata in #[module]
should be used instead.
See modules
metadata in #[component]
builder_modules
See builder_modules
metata in #[component]