use crate::container::registry::ServiceRegistry;
use crate::container::scope::ServiceScope;
use crate::errors::CoreError;
use crate::foundation::traits::Service;
use service_builder::builder;
use std::any::TypeId;
use std::sync::Arc;
#[builder]
pub struct Container {
#[builder(getter, setter)]
registry: ServiceRegistry,
#[builder(getter, setter)]
scope: ServiceScope,
#[builder(default)]
initialized: bool,
}
impl Container {
pub fn new() -> Self {
ContainerBuilder::new()
.registry(ServiceRegistry::new())
.scope(ServiceScope::Singleton)
.build_with_defaults()
.expect("Failed to build container")
}
pub fn register<T>(&mut self, service: T) -> Result<(), CoreError>
where
T: Service + Clone + 'static,
{
self.registry.register_service(service)
}
pub fn register_singleton<T>(&mut self, service: T) -> Result<(), CoreError>
where
T: Service + Clone + 'static,
{
self.registry.register_singleton(service)
}
pub fn register_transient<T>(
&mut self,
factory: Box<dyn Fn() -> T + Send + Sync>,
) -> Result<(), CoreError>
where
T: Service + 'static,
{
self.registry.register_transient(factory)
}
pub fn resolve<T>(&self) -> Result<Arc<T>, CoreError>
where
T: Service + Clone + 'static,
{
self.registry.resolve::<T>()
}
pub fn try_resolve<T>(&self) -> Option<Arc<T>>
where
T: Service + Clone + 'static,
{
self.registry.try_resolve::<T>()
}
pub fn contains<T>(&self) -> bool
where
T: Service + 'static,
{
self.registry.contains::<T>()
}
pub fn validate(&self) -> Result<(), CoreError> {
self.registry.validate()
}
pub async fn initialize(&mut self) -> Result<(), CoreError> {
if self.initialized {
return Ok(());
}
self.registry.initialize_all().await?;
self.initialized = true;
Ok(())
}
pub fn is_initialized(&self) -> bool {
self.initialized
}
pub fn service_count(&self) -> usize {
self.registry.service_count()
}
pub fn registered_services(&self) -> Vec<TypeId> {
self.registry.registered_services()
}
}
impl Default for Container {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for Container {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Container")
.field("service_count", &self.service_count())
.field("initialized", &self.initialized)
.field("scope", &self.scope)
.finish()
}
}