pub trait IServiceCollectionExt: Sized {
// Required methods
fn add_mediator(self) -> Self;
fn add_request_endpoints(self) -> Self;
fn add_controllers(self) -> Self;
fn add_middleware<T>(self) -> Self
where T: IMiddleware + Default + Send + Sync + 'static;
fn add_pipeline<T>(self) -> Self
where T: IPipelineBehavior + Default + Send + Sync + 'static;
fn add_pipeline_with<F>(self, factory: F) -> Self
where F: Fn(&dyn IServiceResolver) -> Arc<dyn IPipelineBehavior> + Send + Sync + 'static;
fn add_hosted_service<T>(self) -> Self
where T: IHostedService + Default + Send + Sync + 'static;
}Expand description
Extension methods for rust_dix::ServiceCollection to enable
framework-level service registration patterns.
Required Methods§
Sourcefn add_mediator(self) -> Self
fn add_mediator(self) -> Self
Register the mediator in the DI container.
The actual IRequestHandler and IEventHandler implementations
are registered via #[rust_dix::module] blocks (re-exported as webx::module).
Sourcefn add_request_endpoints(self) -> Self
fn add_request_endpoints(self) -> Self
Signal that endpoints should be auto-discovered from #[get] / #[endpoint]
annotations at compile time. The actual route table is built during
Host::build() by scanning the inventory for RouteEntry items.
Sourcefn add_controllers(self) -> Self
fn add_controllers(self) -> Self
Register controller types scoped per request.
Sourcefn add_middleware<T>(self) -> Self
fn add_middleware<T>(self) -> Self
Register a middleware type in the DI container as a singleton.
Sourcefn add_pipeline<T>(self) -> Self
fn add_pipeline<T>(self) -> Self
Register a pipeline behavior in the DI container as a singleton.
Requires Default, so it is only usable for behaviors without
dependencies. Use IServiceCollectionExt::add_pipeline_with when the
behavior needs anything from the container.
Sourcefn add_pipeline_with<F>(self, factory: F) -> Self
fn add_pipeline_with<F>(self, factory: F) -> Self
Register a pipeline behavior built from a factory as a singleton.
Unlike IServiceCollectionExt::add_pipeline, the factory receives the
DI resolver, so the behavior can take constructor dependencies — exactly
what the MediatR-style “constructor injection” for pipeline behaviors
means here. The factory runs once (singleton), on first resolution /
build-time validation; the resolver is not available inside
IPipelineBehavior::handle.
The factory is also executed during build() (cycle and captive-dependency
validation), so it must resolve dependencies through the resolver it is
given — resolver.provider_arc() is None there. &dyn IServiceResolver
is object-safe, so get/get_owned (which require a sized resolver) are
unavailable; resolve type-erased instead:
use std::sync::Arc;
use webx::{IServiceCollectionExt, IPipelineBehavior};
svc.add_pipeline_with(|resolver| {
let clock: Arc<Clock> = resolver
.get_any(std::any::type_name::<Clock>())
.and_then(|service| service.downcast::<Arc<Clock>>().ok())
.map(|service| Arc::clone(&*service))
.expect("register Clock before the pipeline");
Arc::new(TimingBehavior { clock }) as Arc<dyn IPipelineBehavior>
})Capturing the dependency when registering is equally valid (and shorter) when the value already exists outside the container:
let clock = Arc::clone(&clock);
svc.add_pipeline_with(move |_| Arc::new(TimingBehavior { clock }))Sourcefn add_hosted_service<T>(self) -> Self
fn add_hosted_service<T>(self) -> Self
Register a hosted service in the DI container as a singleton.
Hosted services are started when the host starts (before accepting requests) and stopped during graceful shutdown.
Analogous to ASP.NET Core’s AddHostedService<T>().
§Example
Host::builder()
.register(|svc| {
svc.add_hosted_service::<DbInitService>()
})
.build()
.run()
.awaitDyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".