elif_core/container/
builder.rs1use crate::container::{Container, ServiceRegistry, ServiceScope};
2use crate::errors::CoreError;
3use crate::foundation::traits::Service;
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>(
46 mut self,
47 factory: Box<dyn Fn() -> T + Send + Sync>,
48 ) -> Result<Self, CoreError>
49 where
50 T: Service + 'static,
51 {
52 self.registry.register_transient(factory)?;
53 Ok(self)
54 }
55
56 pub fn add_services<T>(mut self, services: Vec<T>) -> Result<Self, CoreError>
58 where
59 T: Service + Clone + 'static,
60 {
61 for service in services {
62 self.registry.register_service(service)?;
63 }
64 Ok(self)
65 }
66
67 pub fn configure<F>(self, configure: F) -> Result<Self, CoreError>
69 where
70 F: FnOnce(Self) -> Result<Self, CoreError>,
71 {
72 configure(self)
73 }
74
75 pub fn build(self) -> Result<Container, CoreError> {
77 let container = Container::new();
78 container.validate()?;
80 Ok(container)
81 }
82
83 pub async fn build_and_initialize(self) -> Result<Container, CoreError> {
85 let mut container = self.build()?;
86 container.initialize().await?;
87 Ok(container)
88 }
89}
90
91impl Default for ContainerBuilder {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97#[macro_export]
99macro_rules! container {
100 ($($service:expr),* $(,)?) => {
101 {
102 let mut builder = $crate::container::ContainerBuilder::new();
103 $(
104 builder = builder.add_service($service)?;
105 )*
106 builder.build()
107 }
108 };
109}
110
111#[macro_export]
113macro_rules! singleton_container {
114 ($($service:expr),* $(,)?) => {
115 {
116 let mut builder = $crate::container::ContainerBuilder::new()
117 .with_scope($crate::container::ServiceScope::Singleton);
118 $(
119 builder = builder.add_singleton($service)?;
120 )*
121 builder.build()
122 }
123 };
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use crate::foundation::traits::{FrameworkComponent, Service};
130
131 #[derive(Clone, Debug)]
132 #[allow(dead_code)]
133 struct TestService {
134 name: String,
135 }
136
137 impl FrameworkComponent for TestService {}
138 impl Service for TestService {}
139
140 impl TestService {
141 fn new(name: &str) -> Self {
142 Self {
143 name: name.to_string(),
144 }
145 }
146 }
147
148 #[tokio::test]
149 async fn test_container_builder() -> Result<(), CoreError> {
150 let container = ContainerBuilder::new()
151 .add_service(TestService::new("test1"))?
152 .add_singleton(TestService::new("test2"))?
153 .build_and_initialize()
154 .await?;
155
156 assert!(container.is_initialized());
159
160 Ok(())
161 }
162}