Skip to main content

injectable

Attribute Macro injectable 

Source
#[injectable]
Expand description

Unified DI attribute macro.

Applied to structs, impl blocks, traits, and functions depending on the sub-argument provided:

§On a struct (field injection)

#[injectable]
pub struct UserService {
    db:   Inject<Database>,              // auto-injected
    #[injectable(inject)]
    pool: sqlx::SqlitePool,              // requires annotation
}

§On an impl block (constructor / lifecycle)

#[injectable]
impl UserService {
    #[injectable(ctor)]
    pub fn new(db: Inject<Database>) -> Self { Self { db } }

    #[injectable(post_construct)]
    async fn init(&self) -> HookResult { Ok(()) }

    #[injectable(pre_destruct)]
    async fn shutdown(&self) -> HookResult { Ok(()) }
}

§On a trait (#[injectable(trait)])

Generates the infrastructure needed for Inject<dyn Trait> injection. Use bind!(dyn Trait => Concrete) to wire a concrete implementation.

#[injectable(trait)]
pub trait EmailSender: Send + Sync {
    async fn send(&self, to: &str, body: &str);
}

bind!(dyn EmailSender => SmtpSender);

§On a function (#[injectable(factory)])

Transforms a function whose parameters carry #[injectable(inject)] annotations into an async factory compatible with #[injectable(inject(use_factory_async = path))].

#[injectable(factory)]
pub async fn make_client(
    #[injectable(inject)] cfg: Arc<AppConfig>,
) -> Result<reqwest::Client, reqwest::Error> {
    reqwest::Client::builder()
        .timeout(Duration::from_secs(cfg.timeout_secs))
        .build()
}

#[injectable]
pub struct WeatherService {
    #[injectable(inject(use_factory_async = self::make_client))]
    client: reqwest::Client,
}

§Scope (on structs and impl blocks)

Type-safe idents (recommended):

  • scope = Singleton (default)
  • scope = Transient
  • scope = RequestScoped