ferroui_splat/service_location/
dependency_resolver.rs1use super::service_type::{
5 erase_service, unerase_service, ErasedService, LazyDisposal, RegistrationCallback,
6 ServiceFactory, ServiceType,
7};
8use ferroui_system::IDisposable;
9use std::rc::Rc;
10
11pub trait IReadonlyDependencyResolver {
19 fn get_service_erased(
22 &self,
23 service_type: ServiceType,
24 contract: Option<&str>,
25 ) -> Option<ErasedService>;
26
27 fn get_services_erased(
30 &self,
31 service_type: ServiceType,
32 contract: Option<&str>,
33 ) -> Vec<ErasedService>;
34}
35
36pub trait IMutableDependencyResolver {
41 fn has_registration_erased(&self, service_type: ServiceType, contract: Option<&str>) -> bool;
43
44 fn register_erased(
46 &self,
47 factory: ServiceFactory,
48 service_type: ServiceType,
49 contract: Option<&str>,
50 );
51
52 fn register_constant_erased(
55 &self,
56 value: Option<ErasedService>,
57 disposal: Option<Rc<dyn Fn()>>,
58 service_type: ServiceType,
59 contract: Option<&str>,
60 );
61
62 fn register_lazy_singleton_erased(
66 &self,
67 factory: ServiceFactory,
68 disposal: Option<LazyDisposal>,
69 service_type: ServiceType,
70 contract: Option<&str>,
71 );
72
73 fn unregister_current_erased(&self, service_type: ServiceType, contract: Option<&str>);
75
76 fn unregister_all_erased(&self, service_type: ServiceType, contract: Option<&str>);
78
79 fn service_registration_callback_erased(
82 &self,
83 service_type: ServiceType,
84 contract: Option<&str>,
85 callback: RegistrationCallback,
86 ) -> Rc<dyn IDisposable>;
87}
88
89pub trait IDependencyResolver: IReadonlyDependencyResolver + IMutableDependencyResolver + IDisposable {}
92
93impl<R: IReadonlyDependencyResolver + IMutableDependencyResolver + IDisposable + ?Sized>
94 IDependencyResolver for R
95{
96}
97
98pub trait ReadonlyDependencyResolverExt: IReadonlyDependencyResolver {
100 fn get_service<S: ?Sized + 'static>(&self) -> Option<Rc<S>> {
102 self.get_service_with_contract::<S>(None)
103 }
104
105 fn get_service_with_contract<S: ?Sized + 'static>(&self, contract: Option<&str>) -> Option<Rc<S>> {
107 self.get_service_erased(ServiceType::of::<S>(), contract)
108 .and_then(|service| unerase_service::<S>(&service))
109 }
110
111 fn get_services<S: ?Sized + 'static>(&self) -> Vec<Rc<S>> {
113 self.get_services_with_contract::<S>(None)
114 }
115
116 fn get_services_with_contract<S: ?Sized + 'static>(&self, contract: Option<&str>) -> Vec<Rc<S>> {
118 self.get_services_erased(ServiceType::of::<S>(), contract)
119 .iter()
120 .filter_map(unerase_service::<S>)
121 .collect()
122 }
123}
124
125impl<R: IReadonlyDependencyResolver + ?Sized> ReadonlyDependencyResolverExt for R {}
126
127fn erase_factory<S: ?Sized + 'static>(factory: impl Fn() -> Option<Rc<S>> + 'static) -> ServiceFactory {
128 Rc::new(move || factory().map(erase_service))
129}
130
131pub trait MutableDependencyResolverExt: IMutableDependencyResolver {
133 fn has_registration<S: ?Sized + 'static>(&self) -> bool {
135 self.has_registration_erased(ServiceType::of::<S>(), None)
136 }
137
138 fn has_registration_with_contract<S: ?Sized + 'static>(&self, contract: Option<&str>) -> bool {
140 self.has_registration_erased(ServiceType::of::<S>(), contract)
141 }
142
143 fn register<S: ?Sized + 'static>(&self, factory: impl Fn() -> Option<Rc<S>> + 'static) {
145 self.register_erased(erase_factory(factory), ServiceType::of::<S>(), None);
146 }
147
148 fn register_with_contract<S: ?Sized + 'static>(
150 &self,
151 factory: impl Fn() -> Option<Rc<S>> + 'static,
152 contract: Option<&str>,
153 ) {
154 self.register_erased(erase_factory(factory), ServiceType::of::<S>(), contract);
155 }
156
157 fn register_constant<S: ?Sized + 'static>(&self, value: Rc<S>) {
161 self.register_constant_erased(Some(erase_service(value)), None, ServiceType::of::<S>(), None);
162 }
163
164 fn register_constant_with_contract<S: ?Sized + 'static>(&self, value: Rc<S>, contract: Option<&str>) {
166 self.register_constant_erased(Some(erase_service(value)), None, ServiceType::of::<S>(), contract);
167 }
168
169 fn register_constant_disposable<S: ?Sized + IDisposable + 'static>(&self, value: Rc<S>) {
171 self.register_constant_disposable_with_contract(value, None);
172 }
173
174 fn register_constant_disposable_with_contract<S: ?Sized + IDisposable + 'static>(
177 &self,
178 value: Rc<S>,
179 contract: Option<&str>,
180 ) {
181 let disposed = value.clone();
182 self.register_constant_erased(
183 Some(erase_service(value)),
184 Some(Rc::new(move || disposed.dispose())),
185 ServiceType::of::<S>(),
186 contract,
187 );
188 }
189
190 fn register_lazy_singleton<S: ?Sized + 'static>(&self, factory: impl Fn() -> Option<Rc<S>> + 'static) {
192 self.register_lazy_singleton_erased(erase_factory(factory), None, ServiceType::of::<S>(), None);
193 }
194
195 fn register_lazy_singleton_with_contract<S: ?Sized + 'static>(
197 &self,
198 factory: impl Fn() -> Option<Rc<S>> + 'static,
199 contract: Option<&str>,
200 ) {
201 self.register_lazy_singleton_erased(erase_factory(factory), None, ServiceType::of::<S>(), contract);
202 }
203
204 fn register_lazy_singleton_disposable<S: ?Sized + IDisposable + 'static>(
207 &self,
208 factory: impl Fn() -> Option<Rc<S>> + 'static,
209 ) {
210 self.register_lazy_singleton_disposable_with_contract(factory, None);
211 }
212
213 fn register_lazy_singleton_disposable_with_contract<S: ?Sized + IDisposable + 'static>(
216 &self,
217 factory: impl Fn() -> Option<Rc<S>> + 'static,
218 contract: Option<&str>,
219 ) {
220 let disposal: LazyDisposal = Rc::new(|value: &ErasedService| {
221 if let Some(value) = unerase_service::<S>(value) {
222 value.dispose();
223 }
224 });
225 self.register_lazy_singleton_erased(
226 erase_factory(factory),
227 Some(disposal),
228 ServiceType::of::<S>(),
229 contract,
230 );
231 }
232
233 fn unregister_current<S: ?Sized + 'static>(&self) {
235 self.unregister_current_erased(ServiceType::of::<S>(), None);
236 }
237
238 fn unregister_current_with_contract<S: ?Sized + 'static>(&self, contract: Option<&str>) {
240 self.unregister_current_erased(ServiceType::of::<S>(), contract);
241 }
242
243 fn unregister_all<S: ?Sized + 'static>(&self) {
245 self.unregister_all_erased(ServiceType::of::<S>(), None);
246 }
247
248 fn unregister_all_with_contract<S: ?Sized + 'static>(&self, contract: Option<&str>) {
250 self.unregister_all_erased(ServiceType::of::<S>(), contract);
251 }
252
253 fn service_registration_callback<S: ?Sized + 'static>(
255 &self,
256 callback: impl Fn(&dyn IDisposable) + 'static,
257 ) -> Rc<dyn IDisposable> {
258 self.service_registration_callback_erased(ServiceType::of::<S>(), None, Rc::new(callback))
259 }
260
261 fn service_registration_callback_with_contract<S: ?Sized + 'static>(
263 &self,
264 contract: Option<&str>,
265 callback: impl Fn(&dyn IDisposable) + 'static,
266 ) -> Rc<dyn IDisposable> {
267 self.service_registration_callback_erased(ServiceType::of::<S>(), contract, Rc::new(callback))
268 }
269}
270
271impl<R: IMutableDependencyResolver + ?Sized> MutableDependencyResolverExt for R {}