1use crate::cache::AnyService;
2use crate::entry::IServiceResolver;
3use crate::error::RdiError;
4use crate::provider::ServiceProvider;
5use std::any::{Any, TypeId};
6use std::sync::{Arc, Weak};
7
8pub trait ScopeFactory: Send + Sync {
23 fn create_scope(&self) -> Scope;
26}
27
28pub(crate) struct BuiltinScopeFactory {
34 provider: Weak<ServiceProvider>,
35}
36
37impl BuiltinScopeFactory {
38 pub(crate) fn new(provider: Weak<ServiceProvider>) -> Self {
39 Self { provider }
40 }
41}
42
43impl ScopeFactory for BuiltinScopeFactory {
44 fn create_scope(&self) -> Scope {
45 self.provider.upgrade().map(Scope::new).expect(
46 "ScopeFactory::create_scope: ServiceProvider has been dropped; \
47 the DI container must outlive services created from it",
48 )
49 }
50}
51
52pub(crate) fn builtin_scope_factory(provider: Weak<ServiceProvider>) -> Arc<dyn ScopeFactory> {
54 Arc::new(BuiltinScopeFactory::new(provider))
55}
56
57pub(crate) fn builtin_scope_factory_any(factory: Arc<dyn ScopeFactory>) -> AnyService {
60 Arc::new(factory) as AnyService
61}
62
63pub struct Scope {
81 scope_provider: Arc<ServiceProvider>,
82}
83
84impl Scope {
85 pub(crate) fn new(parent: Arc<ServiceProvider>) -> Self {
86 Self {
87 scope_provider: ServiceProvider::new_scope(&parent),
88 }
89 }
90
91 pub fn scope_provider(&self) -> &Arc<ServiceProvider> {
97 &self.scope_provider
98 }
99
100 pub fn dispose(&self) {
107 self.scope_provider.dispose();
108 }
109
110 pub fn get<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, RdiError> {
111 self.scope_provider.get::<T>()
112 }
113
114 pub fn get_optional<T: ?Sized + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
115 self.scope_provider.get_optional::<T>()
116 }
117
118 pub fn get_keyed<T: ?Sized + Send + Sync + 'static>(
119 &self,
120 key: impl Into<crate::key::ServiceKey>,
121 ) -> Result<Arc<T>, RdiError> {
122 self.scope_provider.get_keyed::<T>(key)
123 }
124
125 pub fn get_async<T: ?Sized + Send + Sync + 'static>(
127 &self,
128 ) -> impl std::future::Future<Output = Result<Arc<T>, RdiError>> + Send + '_ {
129 self.scope_provider.get_async::<T>()
130 }
131
132 pub fn get_keyed_async<T: ?Sized + Send + Sync + 'static>(
134 &self,
135 key: impl Into<crate::key::ServiceKey> + Send,
136 ) -> impl std::future::Future<Output = Result<Arc<T>, RdiError>> + Send + '_ {
137 self.scope_provider.get_keyed_async::<T>(key)
138 }
139
140 pub fn get_owned<T: Send + Sync + 'static>(&self) -> Result<T, RdiError> {
143 self.scope_provider.get_owned::<T>()
144 }
145
146 pub fn try_get_owned<T: Send + Sync + 'static>(&self) -> Option<T> {
148 self.scope_provider.try_get_owned::<T>()
149 }
150
151 pub fn get_keyed_owned<T: Send + Sync + 'static>(
154 &self,
155 key: impl Into<crate::key::ServiceKey>,
156 ) -> Result<T, RdiError> {
157 self.scope_provider.get_keyed_owned::<T>(key)
158 }
159
160 pub fn try_get_keyed_owned<T: Send + Sync + 'static>(
162 &self,
163 key: impl Into<crate::key::ServiceKey>,
164 ) -> Option<T> {
165 self.scope_provider.try_get_keyed_owned::<T>(key)
166 }
167 pub fn get_all<T: ?Sized + Send + Sync + 'static>(&self) -> Vec<Arc<T>> {
169 self.scope_provider.get_all::<T>()
170 }
171
172 pub fn get_all_keyed<T: ?Sized + Send + Sync + 'static>(&self) -> Vec<Arc<T>> {
174 self.scope_provider.get_all_keyed::<T>()
175 }
176
177 pub fn is_registered<T: ?Sized + Send + Sync + 'static>(&self) -> bool {
179 self.scope_provider.is_registered::<T>()
180 }
181
182 pub fn is_registered_keyed<T: ?Sized + Send + Sync + 'static>(
185 &self,
186 key: impl Into<crate::key::ServiceKey>,
187 ) -> bool {
188 self.scope_provider.is_registered_keyed::<T>(key)
189 }
190
191 pub fn async_context(&self) -> Option<crate::AsyncFactoryContext> {
194 self.scope_provider.async_context()
195 }
196
197 pub fn get_named_any(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
198 self.scope_provider.get_named_any(name)
199 }
200
201 pub fn rdi_register_named(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
203 self.scope_provider.rdi_register_named(name, service);
204 }
205
206 pub fn rdi_remove_named(&self, name: &str) {
208 self.scope_provider.rdi_remove_named(name);
209 }
210}
211
212impl Drop for Scope {
213 fn drop(&mut self) {
214 self.dispose();
215 }
216}
217
218impl IServiceResolver for Scope {
219 fn get_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
220 self.scope_provider.get_any(key)
221 }
222 fn get_keyed_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
223 self.scope_provider.get_keyed_any(key, variant)
224 }
225 fn get_keyed_any_key(
226 &self,
227 key: &str,
228 variant: &crate::key::ServiceKey,
229 ) -> Option<Arc<dyn Any + Send + Sync>> {
230 self.scope_provider.get_keyed_any_key(key, variant)
231 }
232 fn try_get_keyed_any_result_key(
233 &self,
234 key: &str,
235 variant: &crate::key::ServiceKey,
236 ) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
237 self.scope_provider
238 .try_get_keyed_any_result_key(key, variant)
239 }
240 fn get_keyed_owned_any_key(
241 &self,
242 key: &str,
243 variant: &crate::key::ServiceKey,
244 ) -> Option<Arc<dyn Any + Send + Sync>> {
245 self.scope_provider.get_keyed_owned_any_key(key, variant)
246 }
247 fn try_get_keyed_owned_any_key(
248 &self,
249 key: &str,
250 variant: &crate::key::ServiceKey,
251 ) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
252 self.scope_provider
253 .try_get_keyed_owned_any_key(key, variant)
254 }
255 fn get_by_type_id(&self, tid: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
256 self.scope_provider.get_by_type_id(tid)
257 }
258 fn get_keyed_by_type_id(&self, tid: TypeId, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
259 self.scope_provider.get_keyed_by_type_id(tid, key)
260 }
261 fn get_all_any(&self, key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
262 self.scope_provider.get_all_any(key)
263 }
264 fn get_all_keyed_any(&self, key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
265 self.scope_provider.get_all_keyed_any(key)
266 }
267 fn get_all_any_result(&self, key: &str) -> Result<Vec<Arc<dyn Any + Send + Sync>>, RdiError> {
268 self.scope_provider.get_all_any_result(key)
269 }
270 fn get_owned_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
271 self.scope_provider.get_owned_any(key)
272 }
273 fn try_get_any_result(
274 &self,
275 key: &str,
276 ) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
277 self.scope_provider.try_get_any_result(key)
278 }
279 fn try_get_keyed_any_result(
280 &self,
281 key: &str,
282 variant: &str,
283 ) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
284 self.scope_provider.try_get_keyed_any_result(key, variant)
285 }
286 fn get_keyed_owned_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
287 self.scope_provider.get_keyed_owned_any(key, variant)
288 }
289 fn provider_arc(&self) -> Option<Arc<ServiceProvider>> {
290 Some(Arc::clone(&self.scope_provider))
294 }
295}
296
297#[cfg(test)]
298mod tests {
299 use super::*;
300 use crate::collection::ServiceCollection;
301 use std::sync::atomic::{AtomicU64, Ordering};
302 #[derive(Debug, PartialEq)]
303 struct Sd(u64);
304 #[test]
305 fn scoped_cached_per_scope() {
306 static NXT: AtomicU64 = AtomicU64::new(0);
307 let p = ServiceCollection::new()
308 .scoped(|_| Arc::new(Sd(NXT.fetch_add(1, Ordering::SeqCst))))
309 .build()
310 .unwrap();
311 let s1 = p.scope();
312 let a = s1.get::<Sd>().unwrap();
313 let b = s1.get::<Sd>().unwrap();
314 assert_eq!(a.0, b.0);
315 let s2 = p.scope();
316 let c = s2.get::<Sd>().unwrap();
317 assert_ne!(a.0, c.0);
318 }
319
320 #[test]
321 fn disposed_scope_rejects_resolution() {
322 let p = ServiceCollection::new()
323 .scoped(|_| Arc::new(Sd(1)))
324 .build()
325 .unwrap();
326 let scope = p.scope();
327 assert!(scope.get::<Sd>().is_ok());
328 scope.dispose();
329 assert!(matches!(
330 scope.get::<Sd>(),
331 Err(crate::error::RdiError::ScopeDisposed)
332 ));
333 assert!(scope.get_optional::<Sd>().is_none());
334 }
335
336 #[test]
337 fn nested_transient_chain_scoped_binds_to_child_scope() {
338 static CORE_CALLS: AtomicU64 = AtomicU64::new(0);
345
346 struct ScopedCore(u64);
347 struct MidTransient {
348 core: Arc<ScopedCore>,
349 }
350 struct OuterTransient {
351 mid: Arc<MidTransient>,
352 }
353
354 let provider = ServiceCollection::new()
355 .scoped(|_| {
356 let n = CORE_CALLS.fetch_add(1, Ordering::SeqCst);
357 Arc::new(ScopedCore(n))
358 })
359 .transient(|r| {
360 let any = r.get_any(std::any::type_name::<ScopedCore>()).unwrap();
361 let outer = any.downcast::<Arc<ScopedCore>>().unwrap();
362 let core: Arc<ScopedCore> = Arc::clone(&*outer);
363 Arc::new(MidTransient { core })
364 })
365 .transient(|r| {
366 let any = r.get_any(std::any::type_name::<MidTransient>()).unwrap();
367 let outer = any.downcast::<Arc<MidTransient>>().unwrap();
368 let mid: Arc<MidTransient> = Arc::clone(&*outer);
369 Arc::new(OuterTransient { mid })
370 })
371 .build()
372 .unwrap();
373
374 let scope1 = provider.scope();
376 let o1: Arc<OuterTransient> = scope1.get().unwrap();
377 assert_eq!(o1.mid.core.0, 0, "scope1 的 ScopedCore 应为序号 0");
378
379 let o1b: Arc<OuterTransient> = scope1.get().unwrap();
382 assert_eq!(o1b.mid.core.0, 0, "scope1 应复用同一 ScopedCore");
383 assert!(
384 Arc::ptr_eq(&o1.mid.core, &o1b.mid.core),
385 "scope1 内 ScopedCore 必须复用"
386 );
387
388 let scope2 = provider.scope();
390 let o2: Arc<OuterTransient> = scope2.get().unwrap();
391 assert_eq!(o2.mid.core.0, 1, "scope2 的 ScopedCore 应为序号 1");
392 assert!(
393 !Arc::ptr_eq(&o1.mid.core, &o2.mid.core),
394 "不同 scope 的 ScopedCore 必须独立"
395 );
396
397 assert!(matches!(
399 provider.get::<ScopedCore>(),
400 Err(crate::error::RdiError::ScopedFromRootProvider { .. })
401 ));
402
403 assert_eq!(
405 CORE_CALLS.load(Ordering::SeqCst),
406 2,
407 "ScopedCore 工厂应执行 2 次(两个子 scope 各一次)"
408 );
409 }
410}