elif_core/container/
ioc_builder.rs1use crate::container::autowiring::Injectable;
2use crate::container::binding::{ServiceBinder, ServiceBindings};
3use crate::container::ioc_container::IocContainer;
4use crate::errors::CoreError;
5
6#[derive(Debug)]
8pub struct IocContainerBuilder {
9 bindings: ServiceBindings,
10}
11
12impl IocContainerBuilder {
13 pub fn new() -> Self {
15 Self {
16 bindings: ServiceBindings::new(),
17 }
18 }
19
20 pub fn build(self) -> Result<IocContainer, CoreError> {
22 let mut container = IocContainer::from_bindings(self.bindings);
23 container.build()?;
24 Ok(container)
25 }
26}
27
28impl ServiceBinder for IocContainerBuilder {
29 fn add_service_descriptor(
30 &mut self,
31 descriptor: crate::container::descriptor::ServiceDescriptor,
32 ) -> Result<&mut Self, crate::errors::CoreError> {
33 self.bindings.add_descriptor(descriptor);
34 Ok(self)
35 }
36
37 fn bind<TInterface: ?Sized + 'static, TImpl: Send + Sync + Default + 'static>(
38 &mut self,
39 ) -> &mut Self {
40 self.bindings.bind::<TInterface, TImpl>();
41 self
42 }
43
44 fn bind_singleton<TInterface: ?Sized + 'static, TImpl: Send + Sync + Default + 'static>(
45 &mut self,
46 ) -> &mut Self {
47 self.bindings.bind_singleton::<TInterface, TImpl>();
48 self
49 }
50
51 fn bind_transient<TInterface: ?Sized + 'static, TImpl: Send + Sync + Default + 'static>(
52 &mut self,
53 ) -> &mut Self {
54 self.bindings.bind_transient::<TInterface, TImpl>();
55 self
56 }
57
58 fn bind_factory<TInterface: ?Sized + 'static, F, T>(&mut self, factory: F) -> &mut Self
59 where
60 F: Fn() -> Result<T, CoreError> + Send + Sync + 'static,
61 T: Send + Sync + 'static,
62 {
63 self.bindings.bind_factory::<TInterface, _, _>(factory);
64 self
65 }
66
67 fn bind_instance<TInterface: ?Sized + 'static, TImpl: Send + Sync + Clone + 'static>(
68 &mut self,
69 instance: TImpl,
70 ) -> &mut Self {
71 self.bindings.bind_instance::<TInterface, TImpl>(instance);
72 self
73 }
74
75 fn bind_named<TInterface: ?Sized + 'static, TImpl: Send + Sync + Default + 'static>(
76 &mut self,
77 name: &str,
78 ) -> &mut Self {
79 self.bindings.bind_named::<TInterface, TImpl>(name);
80 self
81 }
82
83 fn bind_injectable<T: Injectable>(&mut self) -> &mut Self {
84 self.bindings.bind_injectable::<T>();
85 self
86 }
87
88 fn bind_injectable_singleton<T: Injectable>(&mut self) -> &mut Self {
89 self.bindings.bind_injectable_singleton::<T>();
90 self
91 }
92
93 fn bind_with<TInterface: ?Sized + 'static, TImpl: Send + Sync + Default + 'static>(
96 &mut self,
97 ) -> crate::container::binding::AdvancedBindingBuilder<TInterface> {
98 self.bindings.bind_with::<TInterface, TImpl>()
99 }
100
101 fn with_implementation<TInterface: ?Sized + 'static, TImpl: Send + Sync + Default + 'static>(
102 &mut self,
103 config: crate::container::binding::BindingConfig,
104 ) -> &mut Self {
105 self.bindings
106 .with_implementation::<TInterface, TImpl>(config);
107 self
108 }
109
110 fn bind_lazy<TInterface: ?Sized + 'static, F, T>(&mut self, factory: F) -> &mut Self
111 where
112 F: Fn() -> T + Send + Sync + 'static,
113 T: Send + Sync + 'static,
114 {
115 self.bindings.bind_lazy::<TInterface, F, T>(factory);
116 self
117 }
118
119 fn bind_parameterized_factory<TInterface: ?Sized + 'static, P, F, T>(
120 &mut self,
121 factory: F,
122 ) -> &mut Self
123 where
124 F: Fn(P) -> Result<T, CoreError> + Send + Sync + 'static,
125 T: Send + Sync + 'static,
126 P: Send + Sync + 'static,
127 {
128 self.bindings
129 .bind_parameterized_factory::<TInterface, P, F, T>(factory);
130 self
131 }
132
133 fn bind_collection<TInterface: ?Sized + 'static, F>(&mut self, configure: F) -> &mut Self
134 where
135 F: FnOnce(&mut crate::container::binding::CollectionBindingBuilder<TInterface>),
136 {
137 self.bindings.bind_collection::<TInterface, F>(configure);
138 self
139 }
140}
141
142impl Default for IocContainerBuilder {
143 fn default() -> Self {
144 Self::new()
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 trait TestService: Send + Sync {
153 fn get_value(&self) -> String;
154 }
155
156 #[derive(Default)]
157 struct TestServiceImpl;
158
159 unsafe impl Send for TestServiceImpl {}
160 unsafe impl Sync for TestServiceImpl {}
161
162 impl TestService for TestServiceImpl {
163 fn get_value(&self) -> String {
164 "test_value".to_string()
165 }
166 }
167
168 #[test]
169 fn test_ioc_container_builder() {
170 let mut builder = IocContainerBuilder::new();
171 builder.bind::<TestServiceImpl, TestServiceImpl>();
172 let container = builder.build().unwrap();
173
174 let service = container.resolve::<TestServiceImpl>().unwrap();
175 assert_eq!(service.get_value(), "test_value");
176 }
177
178 #[test]
179 fn test_builder_chaining() {
180 let mut builder = IocContainerBuilder::new();
181
182 builder
183 .bind::<TestServiceImpl, TestServiceImpl>()
184 .bind_singleton::<TestServiceImpl, TestServiceImpl>()
185 .bind_transient::<TestServiceImpl, TestServiceImpl>();
186
187 assert!(builder.bindings.count() > 0);
189 }
190}