1use crate::entry::IServiceResolver;
2use crate::error::RdiError;
3use crate::provider::ServiceProvider;
4use std::any::{Any, TypeId};
5use std::sync::Arc;
6
7pub trait ScopeFactory: Send + Sync {
15 fn create_scope(&self) -> Scope;
18}
19
20pub struct Scope {
38 scope_provider: Arc<ServiceProvider>,
39}
40
41impl Scope {
42 pub(crate) fn new(parent: Arc<ServiceProvider>) -> Self {
43 Self {
44 scope_provider: ServiceProvider::new_scope(&parent),
45 }
46 }
47
48 pub fn scope_provider(&self) -> &Arc<ServiceProvider> {
54 &self.scope_provider
55 }
56
57 pub fn dispose(&self) {
79 self.scope_provider.dispose_scoped();
80 }
81
82 pub fn get<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, RdiError> {
83 self.scope_provider.get::<T>()
84 }
85
86 pub fn get_optional<T: ?Sized + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
87 self.scope_provider.get_optional::<T>()
88 }
89
90 pub fn get_keyed<T: ?Sized + Send + Sync + 'static>(&self, key: &str) -> Result<Arc<T>, RdiError> {
91 self.scope_provider.get_keyed::<T>(key)
92 }
93
94 pub async fn get_async<T: ?Sized + Send + Sync + 'static>(
96 &self,
97 ) -> Result<Arc<T>, RdiError> {
98 self.scope_provider.get_async::<T>().await
99 }
100
101 pub async fn get_keyed_async<T: ?Sized + Send + Sync + 'static>(
103 &self,
104 key: &str,
105 ) -> Result<Arc<T>, RdiError> {
106 self.scope_provider.get_keyed_async::<T>(key).await
107 }
108
109 pub fn get_owned<T: Send + Sync + 'static>(&self) -> Result<T, RdiError> {
112 self.scope_provider.get_owned::<T>()
113 }
114
115 pub fn try_get_owned<T: Send + Sync + 'static>(&self) -> Option<T> {
117 self.scope_provider.try_get_owned::<T>()
118 }
119
120 pub fn get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Result<T, RdiError> {
123 self.scope_provider.get_keyed_owned::<T>(key)
124 }
125
126 pub fn try_get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Option<T> {
128 self.scope_provider.try_get_keyed_owned::<T>(key)
129 }
130
131 pub fn get_all<T: ?Sized + Send + Sync + 'static>(&self) -> Vec<Arc<T>> {
132 self.scope_provider.get_all::<T>()
133 }
134
135 pub fn get_named_any(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
136 self.scope_provider.get_named_any(name)
137 }
138
139 pub fn rdi_register_named(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
141 self.scope_provider.rdi_register_named(name, service);
142 }
143
144 pub fn rdi_remove_named(&self, name: &str) {
146 self.scope_provider.rdi_remove_named(name);
147 }
148}
149
150impl Drop for Scope {
151 fn drop(&mut self) {
152 self.dispose();
153 }
154}
155
156impl IServiceResolver for Scope {
157 fn get_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
158 self.scope_provider.get_any(key)
159 }
160 fn get_keyed_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
161 self.scope_provider.get_keyed_any(key, variant)
162 }
163 fn get_by_type_id(&self, tid: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
164 self.scope_provider.get_by_type_id(tid)
165 }
166 fn get_keyed_by_type_id(
167 &self,
168 tid: TypeId,
169 key: &str,
170 ) -> Option<Arc<dyn Any + Send + Sync>> {
171 self.scope_provider.get_keyed_by_type_id(tid, key)
172 }
173 fn get_all_any(&self, key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
174 self.scope_provider.get_all_any(key)
175 }
176 fn get_owned_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
177 self.scope_provider.get_owned_any(key)
178 }
179 fn get_keyed_owned_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
180 self.scope_provider.get_keyed_owned_any(key, variant)
181 }
182 fn provider_arc(&self) -> Option<Arc<ServiceProvider>> {
183 Some(Arc::clone(&self.scope_provider))
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193 use crate::collection::ServiceCollection;
194 use std::sync::atomic::{AtomicU64, Ordering};
195 #[derive(Debug, PartialEq)]
196 struct Sd(u64);
197 #[test]
198 fn scoped_cached_per_scope() {
199 static NXT: AtomicU64 = AtomicU64::new(0);
200 let p = ServiceCollection::new()
201 .scoped(|_| Arc::new(Sd(NXT.fetch_add(1, Ordering::SeqCst))))
202 .build()
203 .unwrap();
204 let s1 = p.scope();
205 let a = s1.get::<Sd>().unwrap();
206 let b = s1.get::<Sd>().unwrap();
207 assert_eq!(a.0, b.0);
208 let s2 = p.scope();
209 let c = s2.get::<Sd>().unwrap();
210 assert_ne!(a.0, c.0);
211 }
212
213 #[test]
214 fn nested_transient_chain_scoped_binds_to_child_scope() {
215 static CORE_CALLS: AtomicU64 = AtomicU64::new(0);
222
223 struct ScopedCore(u64);
224 struct MidTransient {
225 core: Arc<ScopedCore>,
226 }
227 struct OuterTransient {
228 mid: Arc<MidTransient>,
229 }
230
231 let provider = ServiceCollection::new()
232 .scoped(|_| {
233 let n = CORE_CALLS.fetch_add(1, Ordering::SeqCst);
234 Arc::new(ScopedCore(n))
235 })
236 .transient(|r| {
237 let any = r.get_any(std::any::type_name::<ScopedCore>()).unwrap();
238 let outer = any.downcast::<Arc<ScopedCore>>().unwrap();
239 let core: Arc<ScopedCore> = Arc::clone(&*outer);
240 Arc::new(MidTransient { core })
241 })
242 .transient(|r| {
243 let any = r.get_any(std::any::type_name::<MidTransient>()).unwrap();
244 let outer = any.downcast::<Arc<MidTransient>>().unwrap();
245 let mid: Arc<MidTransient> = Arc::clone(&*outer);
246 Arc::new(OuterTransient { mid })
247 })
248 .build()
249 .unwrap();
250
251 let scope1 = provider.scope();
253 let o1: Arc<OuterTransient> = scope1.get().unwrap();
254 assert_eq!(o1.mid.core.0, 0, "scope1 的 ScopedCore 应为序号 0");
255
256 let o1b: Arc<OuterTransient> = scope1.get().unwrap();
259 assert_eq!(o1b.mid.core.0, 0, "scope1 应复用同一 ScopedCore");
260 assert!(
261 Arc::ptr_eq(&o1.mid.core, &o1b.mid.core),
262 "scope1 内 ScopedCore 必须复用"
263 );
264
265 let scope2 = provider.scope();
267 let o2: Arc<OuterTransient> = scope2.get().unwrap();
268 assert_eq!(o2.mid.core.0, 1, "scope2 的 ScopedCore 应为序号 1");
269 assert!(
270 !Arc::ptr_eq(&o1.mid.core, &o2.mid.core),
271 "不同 scope 的 ScopedCore 必须独立"
272 );
273
274 let root_c: Arc<ScopedCore> = provider.get().unwrap();
276 assert_eq!(root_c.0, 2, "根 scope 的 ScopedCore 应为序号 2");
277 assert!(!Arc::ptr_eq(&o1.mid.core, &root_c));
278 assert!(!Arc::ptr_eq(&o2.mid.core, &root_c));
279
280 assert_eq!(
282 CORE_CALLS.load(Ordering::SeqCst),
283 3,
284 "ScopedCore 工厂应执行 3 次(三 scope 各一次)"
285 );
286 }
287}