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}