[−][src]Derive Macro coi::Inject
#[derive(Inject)] { // Attributes available to this derive: #[provides] #[inject] }
Generates an impl for Inject
and also generates a "Provider" struct with its own
Provide
impl.
This derive proc macro impls Inject
on the struct it modifies, and also processes two
attributes:
#[provides]
- Only one of these is allowed per#[derive(Inject)]
. It takes the form
#[provides(<vis> <ty> with <expr>)]
It generates a provider struct with visibility <vis>
that impls Provide
with an output type of Arc<<ty>>
. It will construct <ty>
with <expr>
,
and all params to <expr>
must match the struct fields marked with #[inject]
(see the next
bullet item). <vis>
must match the visibility of <ty>
or you will get code that might not
compile.
#[inject]
- All fields marked#[inject]
are resolved in theprovide
fn described above. Given a field<field_name>: <field_ty>
, this attribute will cause the following resolution to be generated:
let <field_name> = Container::resolve::<<field_ty>>(conainer, "<field_name>");
Because of this, it's important that the field name MUST match the string that's used to
register the provider in the ContainerBuilder
.
Examples
Private trait and no dependencies
use coi::Inject; use coi_derive::Inject; trait Priv: Inject {} #[derive(Inject)] #[provides(dyn Priv with SimpleStruct)] struct SimpleStruct; impl Priv for SimpleStruct {}
Public trait and dependency
use coi::Inject; use coi_derive::Inject; use std::sync::Arc; pub trait Pub: Inject {} pub trait Dependency: Inject {} #[derive(Inject)] #[provides(pub dyn Pub with NewStruct::new(dependency))] struct NewStruct { #[inject] dependency: Arc<dyn Dependency>, } impl NewStruct { fn new(dependency: Arc<dyn Dependency>) -> Self { Self { dependency } } } impl Pub for NewStruct {}
Struct injection
use coi::Inject; use coi_derive::Inject; #[derive(Inject)] #[provides(pub InjectableStruct with InjectableStruct)] struct InjectableStruct;
Unnamed fields
use coi::Inject; use coi_derive::Inject; use std::sync::Arc; #[derive(Inject)] #[provides(Dep1 with Dep1)] struct Dep1; #[derive(Inject)] #[provides(Impl1 with Impl1(dep1))] struct Impl1(#[inject(dep1)] Arc<Dep1>);
Generics
use coi::{container, Inject}; use coi_derive::Inject; #[derive(Inject)] #[provides(Impl1<T> with Impl1::<T>::new())] struct Impl1<T>(T) where T: Default; impl<T> Impl1<T> where T: Default, { fn new() -> Self { Self(Default::default()) } } fn build_container() { // Take note that these providers have to be constructed // with explicit types. let impl1_provider = Impl1Provider::<bool>::new(); let container = container! { impl1 => impl1_provider, }; let _bool_impl = container .resolve::<Impl1<bool>>("impl1") .expect("Should exist"); }
If you need some form of constructor fn that takes arguments that are not injected, then you
need to manually implement the Provide
trait, and this derive will not be useful.