elif_core/container/
builder.rs

1use crate::container::{Container, ServiceRegistry, ServiceScope};
2use crate::foundation::traits::Service;
3use crate::errors::CoreError;
4
5/// Builder for constructing containers with services
6pub struct ContainerBuilder {
7    registry: ServiceRegistry,
8    scope: ServiceScope,
9}
10
11impl ContainerBuilder {
12    /// Create a new container builder
13    pub fn new() -> Self {
14        Self {
15            registry: ServiceRegistry::new(),
16            scope: ServiceScope::Singleton,
17        }
18    }
19    
20    /// Set the default scope for services
21    pub fn with_scope(mut self, scope: ServiceScope) -> Self {
22        self.scope = scope;
23        self
24    }
25    
26    /// Add a service to the container
27    pub fn add_service<T>(mut self, service: T) -> Result<Self, CoreError>
28    where
29        T: Service + Clone + 'static,
30    {
31        self.registry.register_service(service)?;
32        Ok(self)
33    }
34    
35    /// Add a singleton service
36    pub fn add_singleton<T>(mut self, service: T) -> Result<Self, CoreError>
37    where
38        T: Service + Clone + 'static,
39    {
40        self.registry.register_singleton(service)?;
41        Ok(self)
42    }
43    
44    /// Add a transient service with factory
45    pub fn add_transient<T>(mut self, factory: Box<dyn Fn() -> T + Send + Sync>) -> Result<Self, CoreError>
46    where
47        T: Service + 'static,
48    {
49        self.registry.register_transient(factory)?;
50        Ok(self)
51    }
52    
53    /// Add multiple services at once
54    pub fn add_services<T>(mut self, services: Vec<T>) -> Result<Self, CoreError>
55    where
56        T: Service + Clone + 'static,
57    {
58        for service in services {
59            self.registry.register_service(service)?;
60        }
61        Ok(self)
62    }
63    
64    /// Configure the builder from a configuration closure
65    pub fn configure<F>(self, configure: F) -> Result<Self, CoreError>
66    where
67        F: FnOnce(Self) -> Result<Self, CoreError>,
68    {
69        configure(self)
70    }
71    
72    /// Build the container
73    pub fn build(self) -> Result<Container, CoreError> {
74        let container = Container::new();
75        // TODO: Implement proper service transfer from builder registry to container
76        container.validate()?;
77        Ok(container)
78    }
79    
80    /// Build and initialize the container
81    pub async fn build_and_initialize(self) -> Result<Container, CoreError> {
82        let mut container = self.build()?;
83        container.initialize().await?;
84        Ok(container)
85    }
86}
87
88impl Default for ContainerBuilder {
89    fn default() -> Self {
90        Self::new()
91    }
92}
93
94/// Convenience macro for building containers
95#[macro_export]
96macro_rules! container {
97    ($($service:expr),* $(,)?) => {
98        {
99            let mut builder = $crate::container::ContainerBuilder::new();
100            $(
101                builder = builder.add_service($service)?;
102            )*
103            builder.build()
104        }
105    };
106}
107
108/// Convenience macro for building containers with singletons
109#[macro_export]
110macro_rules! singleton_container {
111    ($($service:expr),* $(,)?) => {
112        {
113            let mut builder = $crate::container::ContainerBuilder::new()
114                .with_scope($crate::container::ServiceScope::Singleton);
115            $(
116                builder = builder.add_singleton($service)?;
117            )*
118            builder.build()
119        }
120    };
121}
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126    use crate::foundation::traits::{Service, FrameworkComponent};
127    
128    #[derive(Clone, Debug)]
129    struct TestService {
130        name: String,
131    }
132    
133    impl FrameworkComponent for TestService {}
134    impl Service for TestService {}
135    
136    impl TestService {
137        fn new(name: &str) -> Self {
138            Self {
139                name: name.to_string(),
140            }
141        }
142    }
143    
144    #[tokio::test]
145    async fn test_container_builder() -> Result<(), CoreError> {
146        let container = ContainerBuilder::new()
147            .add_service(TestService::new("test1"))?
148            .add_singleton(TestService::new("test2"))?
149            .build_and_initialize()
150            .await?;
151        
152        // TODO: Fix service transfer from builder to container
153        // assert_eq!(container.service_count(), 2);
154        assert!(container.is_initialized());
155        
156        Ok(())
157    }
158}