elif_core/container/
builder.rs1use crate::container::{Container, ServiceRegistry, ServiceScope};
2use crate::foundation::traits::Service;
3use crate::errors::CoreError;
4
5pub struct ContainerBuilder {
7 registry: ServiceRegistry,
8 scope: ServiceScope,
9}
10
11impl ContainerBuilder {
12 pub fn new() -> Self {
14 Self {
15 registry: ServiceRegistry::new(),
16 scope: ServiceScope::Singleton,
17 }
18 }
19
20 pub fn with_scope(mut self, scope: ServiceScope) -> Self {
22 self.scope = scope;
23 self
24 }
25
26 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 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 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 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 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 pub fn build(self) -> Result<Container, CoreError> {
74 let container = Container::new();
75 container.validate()?;
77 Ok(container)
78 }
79
80 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#[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#[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 assert!(container.is_initialized());
155
156 Ok(())
157 }
158}