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: &str,
121 ) -> Result<Arc<T>, RdiError> {
122 self.scope_provider.get_keyed::<T>(key)
123 }
124
125 pub async fn get_async<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, RdiError> {
127 self.scope_provider.get_async::<T>().await
128 }
129
130 pub async fn get_keyed_async<T: ?Sized + Send + Sync + 'static>(
132 &self,
133 key: &str,
134 ) -> Result<Arc<T>, RdiError> {
135 self.scope_provider.get_keyed_async::<T>(key).await
136 }
137
138 pub fn get_owned<T: Send + Sync + 'static>(&self) -> Result<T, RdiError> {
141 self.scope_provider.get_owned::<T>()
142 }
143
144 pub fn try_get_owned<T: Send + Sync + 'static>(&self) -> Option<T> {
146 self.scope_provider.try_get_owned::<T>()
147 }
148
149 pub fn get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Result<T, RdiError> {
152 self.scope_provider.get_keyed_owned::<T>(key)
153 }
154
155 pub fn try_get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Option<T> {
157 self.scope_provider.try_get_keyed_owned::<T>(key)
158 }
159 pub fn get_all<T: ?Sized + Send + Sync + 'static>(&self) -> Vec<Arc<T>> {
161 self.scope_provider.get_all::<T>()
162 }
163
164 pub fn get_all_keyed<T: ?Sized + Send + Sync + 'static>(&self) -> Vec<Arc<T>> {
166 self.scope_provider.get_all_keyed::<T>()
167 }
168
169 pub fn is_registered<T: ?Sized + Send + Sync + 'static>(&self) -> bool {
171 self.scope_provider.is_registered::<T>()
172 }
173
174 pub fn is_registered_keyed<T: ?Sized + Send + Sync + 'static>(&self, key: &str) -> bool {
176 self.scope_provider.is_registered_keyed::<T>(key)
177 }
178
179 pub fn get_named_any(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
180 self.scope_provider.get_named_any(name)
181 }
182
183 pub fn rdi_register_named(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
185 self.scope_provider.rdi_register_named(name, service);
186 }
187
188 pub fn rdi_remove_named(&self, name: &str) {
190 self.scope_provider.rdi_remove_named(name);
191 }
192}
193
194impl Drop for Scope {
195 fn drop(&mut self) {
196 self.dispose();
197 }
198}
199
200impl IServiceResolver for Scope {
201 fn get_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
202 self.scope_provider.get_any(key)
203 }
204 fn get_keyed_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
205 self.scope_provider.get_keyed_any(key, variant)
206 }
207 fn get_by_type_id(&self, tid: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
208 self.scope_provider.get_by_type_id(tid)
209 }
210 fn get_keyed_by_type_id(&self, tid: TypeId, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
211 self.scope_provider.get_keyed_by_type_id(tid, key)
212 }
213 fn get_all_any(&self, key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
214 self.scope_provider.get_all_any(key)
215 }
216 fn get_all_keyed_any(&self, key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
217 self.scope_provider.get_all_keyed_any(key)
218 }
219 fn get_all_any_result(&self, key: &str) -> Result<Vec<Arc<dyn Any + Send + Sync>>, RdiError> {
220 self.scope_provider.get_all_any_result(key)
221 }
222 fn get_owned_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
223 self.scope_provider.get_owned_any(key)
224 }
225 fn try_get_any_result(
226 &self,
227 key: &str,
228 ) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
229 self.scope_provider.try_get_any_result(key)
230 }
231 fn try_get_keyed_any_result(
232 &self,
233 key: &str,
234 variant: &str,
235 ) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
236 self.scope_provider.try_get_keyed_any_result(key, variant)
237 }
238 fn get_keyed_owned_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
239 self.scope_provider.get_keyed_owned_any(key, variant)
240 }
241 fn provider_arc(&self) -> Option<Arc<ServiceProvider>> {
242 Some(Arc::clone(&self.scope_provider))
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252 use crate::collection::ServiceCollection;
253 use std::sync::atomic::{AtomicU64, Ordering};
254 #[derive(Debug, PartialEq)]
255 struct Sd(u64);
256 #[test]
257 fn scoped_cached_per_scope() {
258 static NXT: AtomicU64 = AtomicU64::new(0);
259 let p = ServiceCollection::new()
260 .scoped(|_| Arc::new(Sd(NXT.fetch_add(1, Ordering::SeqCst))))
261 .build()
262 .unwrap();
263 let s1 = p.scope();
264 let a = s1.get::<Sd>().unwrap();
265 let b = s1.get::<Sd>().unwrap();
266 assert_eq!(a.0, b.0);
267 let s2 = p.scope();
268 let c = s2.get::<Sd>().unwrap();
269 assert_ne!(a.0, c.0);
270 }
271
272 #[test]
273 fn disposed_scope_rejects_resolution() {
274 let p = ServiceCollection::new()
275 .scoped(|_| Arc::new(Sd(1)))
276 .build()
277 .unwrap();
278 let scope = p.scope();
279 assert!(scope.get::<Sd>().is_ok());
280 scope.dispose();
281 assert!(matches!(
282 scope.get::<Sd>(),
283 Err(crate::error::RdiError::ScopeDisposed)
284 ));
285 assert!(scope.get_optional::<Sd>().is_none());
286 }
287
288 #[test]
289 fn nested_transient_chain_scoped_binds_to_child_scope() {
290 static CORE_CALLS: AtomicU64 = AtomicU64::new(0);
297
298 struct ScopedCore(u64);
299 struct MidTransient {
300 core: Arc<ScopedCore>,
301 }
302 struct OuterTransient {
303 mid: Arc<MidTransient>,
304 }
305
306 let provider = ServiceCollection::new()
307 .scoped(|_| {
308 let n = CORE_CALLS.fetch_add(1, Ordering::SeqCst);
309 Arc::new(ScopedCore(n))
310 })
311 .transient(|r| {
312 let any = r.get_any(std::any::type_name::<ScopedCore>()).unwrap();
313 let outer = any.downcast::<Arc<ScopedCore>>().unwrap();
314 let core: Arc<ScopedCore> = Arc::clone(&*outer);
315 Arc::new(MidTransient { core })
316 })
317 .transient(|r| {
318 let any = r.get_any(std::any::type_name::<MidTransient>()).unwrap();
319 let outer = any.downcast::<Arc<MidTransient>>().unwrap();
320 let mid: Arc<MidTransient> = Arc::clone(&*outer);
321 Arc::new(OuterTransient { mid })
322 })
323 .build()
324 .unwrap();
325
326 let scope1 = provider.scope();
328 let o1: Arc<OuterTransient> = scope1.get().unwrap();
329 assert_eq!(o1.mid.core.0, 0, "scope1 的 ScopedCore 应为序号 0");
330
331 let o1b: Arc<OuterTransient> = scope1.get().unwrap();
334 assert_eq!(o1b.mid.core.0, 0, "scope1 应复用同一 ScopedCore");
335 assert!(
336 Arc::ptr_eq(&o1.mid.core, &o1b.mid.core),
337 "scope1 内 ScopedCore 必须复用"
338 );
339
340 let scope2 = provider.scope();
342 let o2: Arc<OuterTransient> = scope2.get().unwrap();
343 assert_eq!(o2.mid.core.0, 1, "scope2 的 ScopedCore 应为序号 1");
344 assert!(
345 !Arc::ptr_eq(&o1.mid.core, &o2.mid.core),
346 "不同 scope 的 ScopedCore 必须独立"
347 );
348
349 assert!(matches!(
351 provider.get::<ScopedCore>(),
352 Err(crate::error::RdiError::ScopedFromRootProvider { .. })
353 ));
354
355 assert_eq!(
357 CORE_CALLS.load(Ordering::SeqCst),
358 2,
359 "ScopedCore 工厂应执行 2 次(两个子 scope 各一次)"
360 );
361 }
362}