elif_core/examples/
module_example.rs1use crate::container::binding::{ServiceBinder, ServiceBindings};
10use crate::container::ioc_builder::IocContainerBuilder;
11use crate::container::module::{ModuleId, ModuleRegistry, ServiceModule};
12use crate::errors::CoreError;
13
14#[derive(Default, Debug)]
18pub struct UserRepository {
19 pub connection_string: String,
20}
21
22impl UserRepository {
23 pub fn find_user(&self, id: u32) -> Option<String> {
24 println!("UserRepository: Finding user {}", id);
25 Some(format!("User-{}", id))
26 }
27}
28
29#[derive(Default, Debug)]
31pub struct UserService {
32 pub cache_enabled: bool,
33}
34
35impl UserService {
36 pub fn get_user(&self, id: u32) -> String {
37 println!("UserService: Getting user {}", id);
38 format!("UserService-{}", id)
39 }
40}
41
42#[derive(Default, Debug)]
44pub struct LoggingService {
45 pub level: String,
46}
47
48impl LoggingService {
49 pub fn log(&self, message: &str) {
50 println!("[{}] {}", self.level, message);
51 }
52}
53
54#[derive(Default, Debug)]
56pub struct ConfigService {
57 pub environment: String,
58}
59
60pub struct CoreInfraModule;
64
65impl ServiceModule for CoreInfraModule {
66 fn name(&self) -> &str {
67 "Core Infrastructure Module"
68 }
69
70 fn description(&self) -> Option<&str> {
71 Some("Provides core infrastructure services like logging and configuration")
72 }
73
74 fn version(&self) -> Option<&str> {
75 Some("1.0.0")
76 }
77
78 fn configure(&self, services: &mut ServiceBindings) {
79 services.bind_singleton::<LoggingService, LoggingService>();
81 services.bind_singleton::<ConfigService, ConfigService>();
82 }
83}
84
85pub struct DataAccessModule;
87
88impl ServiceModule for DataAccessModule {
89 fn name(&self) -> &str {
90 "Data Access Module"
91 }
92
93 fn description(&self) -> Option<&str> {
94 Some("Provides data access repositories and database services")
95 }
96
97 fn version(&self) -> Option<&str> {
98 Some("2.1.0")
99 }
100
101 fn depends_on(&self) -> Vec<ModuleId> {
102 vec![ModuleId::of::<CoreInfraModule>()]
104 }
105
106 fn configure(&self, services: &mut ServiceBindings) {
107 services.bind_singleton::<UserRepository, UserRepository>();
109 }
110}
111
112pub struct BusinessLogicModule;
114
115impl ServiceModule for BusinessLogicModule {
116 fn name(&self) -> &str {
117 "Business Logic Module"
118 }
119
120 fn description(&self) -> Option<&str> {
121 Some("Provides business logic and application services")
122 }
123
124 fn version(&self) -> Option<&str> {
125 Some("1.5.2")
126 }
127
128 fn depends_on(&self) -> Vec<ModuleId> {
129 vec![
131 ModuleId::of::<DataAccessModule>(),
132 ModuleId::of::<CoreInfraModule>(),
133 ]
134 }
135
136 fn configure(&self, services: &mut ServiceBindings) {
137 services.bind::<UserService, UserService>();
139 }
140}
141
142pub fn demonstrate_module_system() -> Result<(), CoreError> {
146 println!("=== ServiceModule Integration Demo ===\n");
147
148 println!("1. Creating module registry...");
150 let mut registry = ModuleRegistry::new();
151
152 registry.register_module(BusinessLogicModule, None)?;
154 registry.register_module(CoreInfraModule, None)?;
155 registry.register_module(DataAccessModule, None)?;
156
157 println!(
158 " ✓ Registered {} modules",
159 registry.get_all_loaded_modules().len()
160 );
161
162 println!("\n2. Calculating dependency load order...");
164 let load_order = registry.calculate_load_order()?;
165
166 for (i, module_id) in load_order.iter().enumerate() {
167 if let Some(loaded_module) = registry.get_loaded_module(module_id) {
168 println!(
169 " {}. {} (v{})",
170 i + 1,
171 loaded_module.metadata.name,
172 loaded_module
173 .metadata
174 .version
175 .as_deref()
176 .unwrap_or("unknown")
177 );
178 }
179 }
180
181 println!("\n3. Configuring services from modules...");
183 let mut container_builder = IocContainerBuilder::new();
184
185 registry.configure_all(&mut container_builder)?;
186 println!(" ✓ All modules configured");
187
188 println!("\n4. Building IoC container...");
190 let container = container_builder.build()?;
191 println!(" ✓ Container built successfully");
192
193 println!("\n5. Initializing modules...");
195 println!(" ✓ All modules initialized (demo - not actually awaited)");
198
199 println!("\n6. Demonstrating service resolution:");
201
202 match container.resolve::<LoggingService>() {
204 Ok(logger) => {
205 logger.log("Logger service resolved from CoreInfraModule");
206 }
207 Err(e) => println!(" ❌ Failed to resolve LoggingService: {}", e),
208 }
209
210 match container.resolve::<ConfigService>() {
211 Ok(_config) => {
212 println!(" ✓ ConfigService resolved from CoreInfraModule");
213 }
214 Err(e) => println!(" ❌ Failed to resolve ConfigService: {}", e),
215 }
216
217 match container.resolve::<UserRepository>() {
218 Ok(repo) => {
219 let user = repo.find_user(123);
220 println!(
221 " ✓ UserRepository resolved from DataAccessModule: {:?}",
222 user
223 );
224 }
225 Err(e) => println!(" ❌ Failed to resolve UserRepository: {}", e),
226 }
227
228 match container.resolve::<UserService>() {
229 Ok(service) => {
230 let user = service.get_user(456);
231 println!(
232 " ✓ UserService resolved from BusinessLogicModule: {}",
233 user
234 );
235 }
236 Err(e) => println!(" ❌ Failed to resolve UserService: {}", e),
237 }
238
239 println!("\n7. Module Status Summary:");
241 for loaded_module in registry.get_all_loaded_modules() {
242 println!(
243 " • {} - {:?}",
244 loaded_module.metadata.name, loaded_module.state
245 );
246 }
247
248 println!("\n🎉 ServiceModule integration demo completed successfully!");
249 Ok(())
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255 use crate::container::module::ModuleState;
256
257 #[test]
258 fn test_module_integration_demo() {
259 let result = demonstrate_module_system();
260 assert!(
261 result.is_ok(),
262 "Module integration demo should complete successfully: {:?}",
263 result
264 );
265 }
266
267 #[test]
268 fn test_module_dependency_resolution() {
269 let mut registry = ModuleRegistry::new();
270
271 registry.register_module(BusinessLogicModule, None).unwrap();
273 registry.register_module(DataAccessModule, None).unwrap();
274 registry.register_module(CoreInfraModule, None).unwrap();
275
276 let load_order = registry.calculate_load_order().unwrap();
277
278 assert_eq!(load_order.len(), 3);
280
281 let order_names: Vec<String> = load_order
282 .iter()
283 .map(|id| {
284 registry
285 .get_loaded_module(id)
286 .unwrap()
287 .metadata
288 .name
289 .clone()
290 })
291 .collect();
292
293 assert_eq!(order_names[0], "Core Infrastructure Module");
294 assert_eq!(order_names[1], "Data Access Module");
295 assert_eq!(order_names[2], "Business Logic Module");
296 }
297
298 #[test]
299 fn test_service_registration_through_modules() {
300 let mut registry = ModuleRegistry::new();
301 registry.register_module(CoreInfraModule, None).unwrap();
302 registry.register_module(DataAccessModule, None).unwrap();
303
304 let mut container_builder = IocContainerBuilder::new();
305 registry.configure_all(&mut container_builder).unwrap();
306
307 let container = container_builder.build().unwrap();
308
309 assert!(container.resolve::<LoggingService>().is_ok());
311 assert!(container.resolve::<ConfigService>().is_ok());
312
313 assert!(container.resolve::<UserRepository>().is_ok());
315 }
316
317 #[test]
318 fn test_module_state_tracking() {
319 let mut registry = ModuleRegistry::new();
320 registry.register_module(CoreInfraModule, None).unwrap();
321
322 let module_id = ModuleId::of::<CoreInfraModule>();
324 let loaded_module = registry.get_loaded_module(&module_id).unwrap();
325 assert_eq!(loaded_module.state, ModuleState::Registered);
326
327 let mut container_builder = IocContainerBuilder::new();
329 registry.configure_all(&mut container_builder).unwrap();
330
331 let loaded_module = registry.get_loaded_module(&module_id).unwrap();
332 assert_eq!(loaded_module.state, ModuleState::Configured);
333 }
334}