ferrous_di/collection/module_system.rs
1//! Service module system for modular registration.
2//!
3//! This module provides traits and functionality for organizing service
4//! registrations into reusable modules.
5
6use crate::{ServiceCollection, DiResult};
7
8/// A module that can register services with a ServiceCollection.
9///
10/// This trait enables modular service registration, similar to .NET's extension methods.
11/// Each module can implement this trait to provide its own service registrations.
12///
13/// # Example
14///
15/// ```rust
16/// use ferrous_di::{ServiceCollection, ServiceModule, ServiceCollectionExt, DiResult, Resolver};
17///
18/// #[derive(Default)]
19/// struct UserConfig;
20///
21/// struct UserService;
22/// impl UserService {
23/// fn new(_config: std::sync::Arc<UserConfig>) -> Self { Self }
24/// }
25///
26/// struct UserModule;
27///
28/// impl ServiceModule for UserModule {
29/// fn register_services(self, services: &mut ServiceCollection) -> DiResult<()> {
30/// services.add_singleton(UserConfig::default());
31/// services.add_scoped_factory::<UserService, _>(|r| {
32/// let config = r.get_required::<UserConfig>();
33/// UserService::new(config)
34/// });
35/// Ok(())
36/// }
37/// }
38///
39/// # fn main() -> DiResult<()> {
40/// // Usage
41/// let mut services = ServiceCollection::new();
42/// let provider = services.add_module(UserModule)?.build();
43/// # Ok(())
44/// # }
45/// ```
46pub trait ServiceModule {
47 /// Register this module's services with the ServiceCollection.
48 fn register_services(self, services: &mut ServiceCollection) -> DiResult<()>;
49}
50
51/// Extension trait for ServiceCollection that provides module registration capabilities.
52///
53/// This trait enables .NET-style extension method chaining for modules.
54pub trait ServiceCollectionExt {
55 /// Add a module to the service collection using extension method syntax.
56 ///
57 /// # Example
58 ///
59 /// ```rust
60 /// use ferrous_di::{ServiceCollection, ServiceCollectionExt, ServiceModule, DiResult};
61 ///
62 /// struct DatabaseModule;
63 /// impl ServiceModule for DatabaseModule {
64 /// fn register_services(self, _: &mut ServiceCollection) -> DiResult<()> { Ok(()) }
65 /// }
66 ///
67 /// struct UserModule;
68 /// impl ServiceModule for UserModule {
69 /// fn register_services(self, _: &mut ServiceCollection) -> DiResult<()> { Ok(()) }
70 /// }
71 ///
72 /// # fn main() -> DiResult<()> {
73 /// let mut services = ServiceCollection::new();
74 /// let provider = services
75 /// .add_module(DatabaseModule)?
76 /// .add_module(UserModule)?
77 /// .build();
78 /// # Ok(())
79 /// # }
80 /// ```
81 fn add_module<M: ServiceModule>(self, module: M) -> DiResult<Self>
82 where
83 Self: Sized;
84}
85
86impl ServiceCollectionExt for ServiceCollection {
87 fn add_module<M: ServiceModule>(mut self, module: M) -> DiResult<Self> {
88 module.register_services(&mut self)?;
89 Ok(self)
90 }
91}
92
93/// Additional extension trait for ServiceCollection that provides fluent module registration
94/// that matches the existing &mut Self pattern.
95pub trait ServiceCollectionModuleExt {
96 /// Add a module to the service collection in-place.
97 /// Returns a DiResult to handle any registration errors.
98 fn add_module_mut<M: ServiceModule>(&mut self, module: M) -> DiResult<&mut Self>;
99}
100
101impl ServiceCollectionModuleExt for ServiceCollection {
102 fn add_module_mut<M: ServiceModule>(&mut self, module: M) -> DiResult<&mut Self> {
103 module.register_services(self)?;
104 Ok(self)
105 }
106}