pub struct Container { /* private fields */ }Expand description
The dependency injection container.
The container holds the typed singleton store, the provider registry,
and registered destructors for #[injectable(pre_destruct)] hooks. It is
constructed via Container::builder().
§Resolution Strategy
- Types implementing
Injectableare resolved via static providers - Types registered via
ContainerBuilder::register()are resolved via the dynamic provider registry - All other types return
MissingDependencyerrors
§Lifecycle
- Use
Container::resolveto obtain instances - Use
Container::shutdownto run#[injectable(pre_destruct)]hooks in reverse construction order
§Example
// Types you own: derive Injectable
#[injectable]
#[derive(Default)]
pub struct UserService { ... }
// Types you don't own: register a provider
let container = Container::builder()
.register(DynProvider::new(|| {
Ok(reqwest::Client::new())
}))
.build()
.await?;
let service = container.resolve::<UserService>().await?;
let client = container.resolve_external::<reqwest::Client>().await?;
// On shutdown, call pre_destruct hooks
container.shutdown().await;Implementations§
Source§impl Container
impl Container
Sourcepub fn builder() -> ContainerBuilder
pub fn builder() -> ContainerBuilder
Create a new container builder.
Sourcepub async fn resolve<T: Injectable>(&self) -> InjectableResult<T>
pub async fn resolve<T: Injectable>(&self) -> InjectableResult<T>
Sourcepub async fn resolve_external<T: Send + Sync + 'static>(
&self,
) -> InjectableResult<T>
pub async fn resolve_external<T: Send + Sync + 'static>( &self, ) -> InjectableResult<T>
Resolve an external type from the provider registry.
Use this for types that don’t implement Injectable but have
been registered via ContainerBuilder::register.
§Example
let client = app.resolve_external::<reqwest::Client>().await?;Sourcepub async fn resolve_external_with_token<T: Send + Sync + 'static>(
&self,
token: &str,
) -> InjectableResult<T>
pub async fn resolve_external_with_token<T: Send + Sync + 'static>( &self, token: &str, ) -> InjectableResult<T>
Resolve a named external type by token.
Use this when multiple providers of the same type were registered with
different tokens via ContainerBuilder::register("token", DynProvider::…).
§Example
let primary: Pool = container.resolve_external_with_token("primary").await?;
let replica: Pool = container.resolve_external_with_token("replica").await?;Sourcepub async fn try_resolve_external_with_token<T: Send + Sync + 'static>(
&self,
token: &str,
) -> InjectableResult<Option<T>>
pub async fn try_resolve_external_with_token<T: Send + Sync + 'static>( &self, token: &str, ) -> InjectableResult<Option<T>>
Resolve a named external type by token, returning None if not registered.
Sourcepub fn context(&self) -> &ResolveContext
pub fn context(&self) -> &ResolveContext
Get a reference to the internal resolve context.
Useful for manual extraction in advanced scenarios.
Sourcepub fn registered_types(&self) -> Vec<&'static str>
pub fn registered_types(&self) -> Vec<&'static str>
Returns the names of all #[injectable] types registered in the container.
This includes every type that was annotated with #[injectable] and
linked into the binary — useful for debugging MissingDependency errors
and asserting DI registration in tests.
§Example
let container = Container::builder().build().await?;
assert!(container.registered_types().contains(&"Database"));Sourcepub async fn try_resolve<T: Injectable>(&self) -> InjectableResult<Option<T>>
pub async fn try_resolve<T: Injectable>(&self) -> InjectableResult<Option<T>>
Resolve a type, returning None instead of an error if it is not registered.
Maps MissingDependency → Ok(None) and propagates all other errors.
Sourcepub async fn try_resolve_external<T: Send + Sync + 'static>(
&self,
) -> InjectableResult<Option<T>>
pub async fn try_resolve_external<T: Send + Sync + 'static>( &self, ) -> InjectableResult<Option<T>>
Resolve an external type, returning None instead of an error if not registered.
Sourcepub async fn shutdown(&self) -> InjectableResult<()>
pub async fn shutdown(&self) -> InjectableResult<()>
Shut down the container, running all #[injectable(pre_destruct)] hooks.
Hooks are called in reverse construction order — the most recently constructed instance is destroyed first. This ensures that dependencies are not destroyed before the types that depend on them.
All destructors are called even if some fail (best-effort cleanup).
If any hooks fail, returns InjectableError::ShutdownFailed
containing all accumulated errors.
§Example
let container = Container::builder()
.build()
.await?;
let service = container.resolve::<Database>().await?;
// On application shutdown:
container.shutdown().await?;Sourcepub async fn destructor_count(&self) -> usize
pub async fn destructor_count(&self) -> usize
Returns the number of registered destructors.
This counts instances that have #[injectable(has_pre_destruct)]
and have been resolved through this container.