use std::collections::HashMap;
use std::sync::Arc;
pub struct DIContainer {
dependencies: HashMap<String, Box<dyn std::any::Any + Send + Sync>>,
singletons: HashMap<String, Arc<dyn std::any::Any + Send + Sync>>,
factories: HashMap<String, Box<dyn Fn() -> Box<dyn std::any::Any + Send + Sync> + Send + Sync>>,
config: super::DIConfiguration,
}
impl std::fmt::Debug for DIContainer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "DIContainer {{ dependencies: <{}>, singletons: <{}>, factories: <{}>, config: {:?} }}",
self.dependencies.len(),
self.singletons.len(),
self.factories.len(),
self.config)
}
}
impl Default for DIContainer {
fn default() -> Self {
Self::new()
}
}
impl DIContainer {
pub fn new() -> Self {
Self {
dependencies: HashMap::new(),
singletons: HashMap::new(),
factories: HashMap::new(),
config: super::DIConfiguration::default(),
}
}
pub fn register<T: Send + Sync + 'static>(&mut self, name: &str, instance: T) {
self.dependencies.insert(
name.to_string(),
Box::new(instance)
);
}
pub fn register_singleton<T: Send + Sync + 'static>(&mut self, name: &str, instance: T) {
self.singletons.insert(
name.to_string(),
Arc::new(instance)
);
}
pub fn register_factory<T: Send + Sync + 'static, F>(&mut self, name: &str, factory: F)
where
F: Fn() -> T + Send + Sync + 'static,
{
self.factories.insert(
name.to_string(),
Box::new(move || Box::new(factory()))
);
}
pub fn resolve<T: Send + Sync + 'static>(&self, name: &str) -> Option<&T> {
if let Some(singleton) = self.singletons.get(name) {
return singleton.downcast_ref::<T>();
}
if let Some(dependency) = self.dependencies.get(name) {
return dependency.downcast_ref::<T>();
}
None
}
pub fn create<T: Send + Sync + 'static>(&self, name: &str) -> Option<T> {
if let Some(factory) = self.factories.get(name) {
let instance = factory();
return instance.downcast::<T>().ok().map(|boxed| *boxed);
}
None
}
pub fn has_dependency(&self, name: &str) -> bool {
self.dependencies.contains_key(name) ||
self.singletons.contains_key(name) ||
self.factories.contains_key(name)
}
pub fn list_dependencies(&self) -> Vec<String> {
let mut deps: Vec<String> = self.dependencies.keys().cloned().collect();
deps.extend(self.singletons.keys().cloned());
deps.extend(self.factories.keys().cloned());
deps.sort();
deps.dedup();
deps
}
}