Skip to main content

rust_dix/
provider.rs

1use crate::cache::{AnyService, LazyCache};
2use crate::entry::{
3    AsyncServiceFactory, IServiceResolver, ServiceEntry, ServiceFactory, ServiceLifetime,
4    ServiceStore,
5};
6use crate::error::RdiError;
7use crate::scope::ScopeFactory;
8use crate::validation::ValidationResolver;
9use std::any::{Any, TypeId};
10use std::cell::RefCell;
11use std::collections::HashMap;
12use std::panic::AssertUnwindSafe;
13use std::sync::{Arc, Mutex, OnceLock, RwLock, Weak};
14
15thread_local! {
16    /// Runtime resolution stack for Scoped/Transient cycle detection.
17    static RESOLVING: RefCell<Vec<(usize, &'static str)>> = const { RefCell::new(Vec::new()) };
18}
19
20struct ResolveGuard;
21
22impl Drop for ResolveGuard {
23    fn drop(&mut self) {
24        RESOLVING.with(|stack| {
25            stack.borrow_mut().pop();
26        });
27    }
28}
29
30fn enter_resolve(cache_key: usize, type_name: &'static str) -> Result<ResolveGuard, RdiError> {
31    RESOLVING.with(|stack| {
32        let mut s = stack.borrow_mut();
33        if s.iter().any(|(k, _)| *k == cache_key) {
34            let mut chain: Vec<&str> = s.iter().map(|(_, n)| *n).collect();
35            chain.push(type_name);
36            return Err(RdiError::CircularDependency(chain.join(" -> ")));
37        }
38        s.push((cache_key, type_name));
39        Ok(ResolveGuard)
40    })
41}
42
43pub struct ServiceProvider {
44    /// Service registry. Shared across root + scope-derived providers via `Arc`.
45    store: Arc<ServiceStore>,
46    /// String → TypeId lookup for IServiceResolver string-based resolution.
47    /// Shared across root + scope-derived providers via `Arc`.
48    type_map: Arc<HashMap<&'static str, TypeId>>,
49    /// Singleton 实例缓存(per-key `OnceLock`,多线程下工厂只执行一次)。
50    /// build 阶段 validation + Phase 2 eager init 预热,运行时 lazy fallback。
51    /// Shared across root + scope-derived providers via `Arc`(全局单例语义)。
52    singleton_cache: Arc<LazyCache>,
53    /// Root scope 的 Scoped 实例缓存。
54    ///
55    /// ServiceProvider 本身即 MEDI 的 root scope:从根直接解析 Scoped 服务时,
56    /// 实例在此缓存中复用,语义等同于在根 scope 内单例化。
57    /// 子 Scope(通过 [`ServiceProvider::scope`] 创建)拥有独立的 scoped_cache,不回退到此缓存。
58    /// per-key `OnceLock` 保证多线程下工厂只执行一次,无 TOCTOU 竞态。
59    /// **每个 provider 独立**:root 与 scope-derived 各自持有一份。
60    root_scoped_cache: LazyCache,
61    /// String-keyed registry for cross-DLL (cdylib) service access.
62    /// Rust's `TypeId` differs across compilation units, so named
63    /// lookup is the only reliable mechanism for plugin services.
64    /// Shared across root + scope-derived providers via `Arc`.
65    pub(crate) named: Arc<RwLock<HashMap<String, Arc<dyn Any + Send + Sync>>>>,
66    /// Self-referential weak pointer, initialized by [`Self::new`] or
67    /// [`Self::new_scope`]. Enables [`IServiceResolver::provider_arc`] to hand
68    /// out `Arc<ServiceProvider>` to services using `#[inject(provider)]`.
69    /// **每个 provider 独立**:scope-derived provider 的 self_weak 指向自身。
70    self_weak: OnceLock<Weak<ServiceProvider>>,
71    /// Cleanup closures for scoped services registered via [`Self::register_disposable`].
72    /// Populated during factory execution, drained by `Self::dispose_scoped`.
73    /// **每个 provider 独立**:scope-derived provider 的 disposables 绑定到当前 scope。
74    disposables: Mutex<Vec<Box<dyn FnOnce() + Send>>>,
75}
76
77impl ServiceProvider {
78    pub(crate) fn new(store: ServiceStore) -> Result<Arc<Self>, RdiError> {
79        // Reject async registrations on the sync build path.
80        if let Some(entry) = store
81            .values()
82            .flat_map(|entries| entries.iter())
83            .find(|e| e.async_factory.is_some())
84        {
85            return Err(RdiError::AsyncServiceRequiresBuildAsync {
86                service: entry.type_name.to_string(),
87            });
88        }
89
90        // Build type_name → TypeId lookup table for string-based resolution
91        let mut type_map = HashMap::new();
92        for (&tid, entries) in &store {
93            if let Some(e) = entries.first() {
94                type_map.entry(e.type_name).or_insert(tid);
95            }
96        }
97
98        // Phase 0: Validate dependencies (cycle detection, captive dependency).
99        let singleton_cache = Arc::new(LazyCache::new());
100        Self::validate_dependencies(&store, &singleton_cache)?;
101
102        // Phase 1: create the provider in an Arc and initialize self_weak.
103        let sp_arc = Arc::new(Self {
104            store: Arc::new(store),
105            type_map: Arc::new(type_map),
106            singleton_cache,
107            root_scoped_cache: LazyCache::new(),
108            named: Arc::new(RwLock::new(HashMap::new())),
109            self_weak: OnceLock::new(),
110            disposables: Mutex::new(Vec::new()),
111        });
112        sp_arc
113            .self_weak
114            .get_or_init(|| Arc::downgrade(&sp_arc));
115
116        Self::init_sync_singletons(&sp_arc);
117        Ok(sp_arc)
118    }
119
120    /// Collect sync singleton entries and eagerly execute their factories.
121    ///
122    /// Reuses instances cached by validation (build time) so factories aren't
123    /// double-fired. Called by both `new` and `new_async` (async singletons skipped).
124    fn init_sync_singletons(sp_arc: &Arc<Self>) {
125        let singleton_entries: Vec<(usize, ServiceFactory)> = sp_arc
126            .store
127            .values()
128            .flat_map(|entries| entries.iter())
129            .filter(|e| e.lifetime == ServiceLifetime::Singleton && e.async_factory.is_none())
130            .map(|e| (e.cache_key, e.factory.clone()))
131            .collect();
132
133        for (ck, factory) in &singleton_entries {
134            let resolver = sp_arc.as_ref() as &dyn IServiceResolver;
135            let factory = factory.clone();
136            sp_arc
137                .singleton_cache
138                .get_or_init_with(*ck, move || factory(resolver));
139        }
140    }
141
142    /// Build a `ServiceProvider` with async factory support.
143    ///
144    /// Async singleton factories are executed during build and their results
145    /// are cached. Async transient/scoped factories are stored for later
146    /// resolution via `get_async` / `get_keyed_async`.
147    ///
148    /// Returns `Arc<ServiceProvider>` so that `provider_arc()` works for
149    /// async resolution (async factories receive `Arc<ServiceProvider>`).
150    pub(crate) async fn new_async(
151        store: ServiceStore,
152    ) -> Result<Arc<Self>, RdiError> {
153        // Build type_name → TypeId lookup
154        let mut type_map = HashMap::new();
155        for (&tid, entries) in &store {
156            if let Some(e) = entries.first() {
157                type_map.entry(e.type_name).or_insert(tid);
158            }
159        }
160
161        // Phase 0: Validate sync singleton dependencies (async singletons skipped).
162        let singleton_cache = Arc::new(LazyCache::new());
163        Self::validate_dependencies(&store, &singleton_cache)?;
164
165        // Phase 1: create the provider in an Arc.
166        let sp_arc = Arc::new(Self {
167            store: Arc::new(store),
168            type_map: Arc::new(type_map),
169            singleton_cache,
170            root_scoped_cache: LazyCache::new(),
171            named: Arc::new(RwLock::new(HashMap::new())),
172            self_weak: OnceLock::new(),
173            disposables: Mutex::new(Vec::new()),
174        });
175        sp_arc
176            .self_weak
177            .get_or_init(|| Arc::downgrade(&sp_arc));
178
179        Self::init_sync_singletons(&sp_arc);
180
181        // Phase 2: execute async singleton factories.
182        let async_singletons: Vec<(usize, AsyncServiceFactory)> = sp_arc
183            .store
184            .values()
185            .flat_map(|entries| entries.iter())
186            .filter(|e| e.lifetime == ServiceLifetime::Singleton && e.async_factory.is_some())
187            .map(|e| (e.cache_key, e.async_factory.clone().unwrap()))
188            .collect();
189
190        for (ck, async_factory) in async_singletons {
191            let result = async_factory(Arc::clone(&sp_arc)).await;
192            sp_arc.singleton_cache.get_or_init_with(ck, || result);
193        }
194
195        Ok(sp_arc)
196    }
197
198    /// 创建一个 scope 范围的 ServiceProvider,共享 store/type_map/singleton_cache/named,
199    /// 独立 root_scoped_cache 和 self_weak。
200    ///
201    /// 供 [`Scope::new`](crate::scope::Scope::new) 调用。这使 `#[inject(provider)]`
202    /// 字段拿到的是 **scope 范围的 provider** 而非根 provider——经该字段解析 Scoped 服务
203    /// 会命中 scope 自己的 `root_scoped_cache`,符合 MEDI `IServiceScope` 语义。
204    ///
205    /// 与 [`Self::new`] 一样初始化 self_weak,使 scope provider 自身可被
206    /// `provider_arc()` 返回。
207    pub(crate) fn new_scope(parent: &Arc<Self>) -> Arc<Self> {
208        let sp = Self {
209            store: Arc::clone(&parent.store),
210            type_map: Arc::clone(&parent.type_map),
211            singleton_cache: Arc::clone(&parent.singleton_cache),
212            root_scoped_cache: LazyCache::new(),
213            named: Arc::clone(&parent.named),
214            self_weak: OnceLock::new(),
215            disposables: Mutex::new(Vec::new()),
216        };
217        let arc = Arc::new(sp);
218        let this: &Self = &arc;
219        this.self_weak.get_or_init(|| Arc::downgrade(&arc));
220        arc
221    }
222
223    /// Register a cleanup closure for a scoped service.
224    ///
225    /// Called by users who want to ensure their scoped services are cleaned up
226    /// deterministically when the scope ends. The closure is invoked when
227    /// `Self::dispose_scoped` is called (via [`Scope::dispose`](crate::scope::Scope::dispose)
228    /// or [`Scope`](crate::scope::Scope) Drop).
229    pub fn register_disposable(&self, cleanup: Box<dyn FnOnce() + Send>) {
230        self.disposables.lock().unwrap().push(cleanup);
231    }
232
233    /// Drain and execute all registered cleanup closures.
234    ///
235    /// Called by [`Scope::dispose`](crate::scope::Scope::dispose). Acquires the
236    /// disposables lock (waits if a concurrent `register_disposable` is in
237    /// progress), takes the queue, then runs cleanups **without** holding the
238    /// lock — so cleanup callbacks may safely call `register_disposable` again.
239    pub(crate) fn dispose_scoped(&self) {
240        let to_run: Vec<Box<dyn FnOnce() + Send>> = {
241            let mut guard = self.disposables.lock().unwrap();
242            std::mem::take(&mut *guard)
243        };
244        for cleanup in to_run {
245            cleanup();
246        }
247    }
248
249    /// Validate all dependencies: detect cycles and captive dependencies.
250    /// Instances built during validation are stored in `cache` so they can
251    /// be reused by the subsequent eager-init phase.
252    fn validate_dependencies(store: &ServiceStore, cache: &LazyCache) -> Result<(), RdiError> {
253        // Build TypeId → type_name map for error messages
254        let type_names: HashMap<TypeId, &'static str> = store
255            .iter()
256            .map(|(&tid, entries)| {
257                let name = entries.first().map(|e| e.type_name).unwrap_or("<unknown>");
258                (tid, name)
259            })
260            .collect();
261
262        // Validate each sync singleton by attempting to resolve it.
263        // Scoped/Transient are not eagerly executed at build (avoids side effects);
264        // their cycles are detected at runtime via a thread-local resolution stack.
265        for entries in store.values() {
266            for entry in entries {
267                if entry.lifetime == ServiceLifetime::Singleton && entry.async_factory.is_none() {
268                    let resolver = ValidationResolver::new(store, &type_names, cache);
269                    let type_name = entry.type_name;
270                    let key = entry.key.clone();
271
272                    let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
273                        match &key {
274                            Some(k) => resolver.get_keyed_any(type_name, k),
275                            None => resolver.get_any(type_name),
276                        }
277                    }));
278
279                    if let Some(err) = resolver.take_error() {
280                        return Err(err);
281                    }
282
283                    match result {
284                        Ok(_) => {}
285                        Err(panic_info) => {
286                            return Err(RdiError::from_panic_payload(type_name, panic_info));
287                        }
288                    }
289                }
290            }
291        }
292
293        Ok(())
294    }
295
296    /// Resolve a service by type. Works uniformly for concrete types and trait objects.
297    /// Returns `Err(RdiError::ServiceNotFound)` if not registered.
298    ///
299    /// [`ScopeFactory`] is always available from a built provider (no manual
300    /// registration required). An explicit `singleton::<dyn ScopeFactory>(...)`
301    /// registration still takes precedence.
302    pub fn get<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, RdiError> {
303        let type_name = std::any::type_name::<T>();
304        match self.resolve_optional::<T>() {
305            Ok(Some(v)) => Ok(v),
306            Ok(None) => Err(RdiError::not_found(type_name, None)),
307            Err(e) => Err(e),
308        }
309    }
310
311    /// Resolve a service by type, returning `None` if not registered.
312    pub fn get_optional<T: ?Sized + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
313        self.resolve_optional::<T>().ok().flatten()
314    }
315
316    /// Resolve an async service (transient or scoped) by type.
317    ///
318    /// - Singletons are resolved synchronously (already cached during `build_async`).
319    /// - Scoped services are cached in `root_scoped_cache` (one instance per scope).
320    /// - Transient services call the async factory fresh each time.
321    pub async fn get_async<T: ?Sized + Send + Sync + 'static>(
322        &self,
323    ) -> Result<Arc<T>, RdiError> {
324        let type_name = std::any::type_name::<T>();
325        let tid = TypeId::of::<T>();
326        let entry = self
327            .store
328            .get(&tid)
329            .and_then(|entries| entries.iter().find(|e| e.key.is_none()))
330            .ok_or_else(|| RdiError::not_found(type_name, None))?;
331
332        if entry.lifetime == ServiceLifetime::Singleton {
333            return self.get::<T>();
334        }
335
336        match self.resolve_async_any(entry, type_name).await? {
337            Some(arc_any) => Self::extract(arc_any).ok_or_else(|| RdiError::not_found(type_name, None)),
338            None => self.get::<T>(),
339        }
340    }
341
342    /// Resolve an async keyed service by type and key.
343    pub async fn get_keyed_async<T: ?Sized + Send + Sync + 'static>(
344        &self,
345        key: &str,
346    ) -> Result<Arc<T>, RdiError> {
347        let type_name = std::any::type_name::<T>();
348        let tid = TypeId::of::<T>();
349        let entry = self
350            .store
351            .get(&tid)
352            .and_then(|entries| entries.iter().find(|e| e.key.as_deref() == Some(key)))
353            .ok_or_else(|| RdiError::keyed_not_found(type_name, key, None))?;
354
355        if entry.lifetime == ServiceLifetime::Singleton {
356            return self.get_keyed::<T>(key);
357        }
358
359        match self.resolve_async_any(entry, type_name).await? {
360            Some(arc_any) => {
361                Self::extract(arc_any).ok_or_else(|| RdiError::keyed_not_found(type_name, key, None))
362            }
363            None => self.get_keyed::<T>(key),
364        }
365    }
366
367    /// Resolve async Scoped/Transient factory, returning `Some(AnyService)`.
368    /// Returns `None` if the entry has no async factory (caller falls back to sync path).
369    async fn resolve_async_any(
370        &self,
371        entry: &ServiceEntry,
372        type_name: &'static str,
373    ) -> Result<Option<AnyService>, RdiError> {
374        match entry.lifetime {
375            ServiceLifetime::Scoped => {
376                let async_factory = entry
377                    .async_factory
378                    .clone()
379                    .ok_or_else(|| RdiError::not_found(type_name, None))?;
380                let provider_arc = self.provider_arc().ok_or_else(|| RdiError::FactoryPanic {
381                    service: type_name.to_string(),
382                    payload: "provider_arc() returned None for async resolution".into(),
383                })?;
384                self.root_scoped_cache
385                    .get_or_init_with_async(entry.cache_key, || {
386                        Self::run_async_factory_safely(type_name, async_factory, provider_arc)
387                    })
388                    .await
389                    .map(Some)
390            }
391            ServiceLifetime::Transient => {
392                if let Some(async_factory) = entry.async_factory.clone() {
393                    let provider_arc = self.provider_arc().ok_or_else(|| RdiError::FactoryPanic {
394                        service: type_name.to_string(),
395                        payload: "provider_arc() returned None for async resolution".into(),
396                    })?;
397                    Self::run_async_factory_safely(type_name, async_factory, provider_arc)
398                        .await
399                        .map(Some)
400                } else {
401                    Ok(None)
402                }
403            }
404            _ => Ok(None),
405        }
406    }
407
408    /// Execute an async factory and catch panics, converting to `RdiError::FactoryPanic`.
409    ///
410    /// async 工厂 panic 无法自然传播到 `.await` 点之外(会终止 task),
411    /// 需用 `catch_unwind` 捕获并转为类型安全的 `RdiError`。
412    async fn run_async_factory_safely(
413        type_name: &'static str,
414        async_factory: AsyncServiceFactory,
415        provider_arc: Arc<ServiceProvider>,
416    ) -> Result<AnyService, RdiError> {
417        let fut = async_factory(provider_arc);
418        match futures::FutureExt::catch_unwind(AssertUnwindSafe(fut)).await {
419            Ok(arc_any) => Ok(arc_any),
420            Err(payload) => Err(RdiError::from_panic_payload(type_name, payload)),
421        }
422    }
423
424    /// Resolve a keyed service by type and key.
425    /// Returns `Err(RdiError::KeyedServiceNotFound)` if not found.
426    pub fn get_keyed<T: ?Sized + Send + Sync + 'static>(&self, key: &str) -> Result<Arc<T>, RdiError> {
427        let type_name = std::any::type_name::<T>();
428        match self.resolve_keyed_optional::<T>(key) {
429            Ok(Some(v)) => Ok(v),
430            Ok(None) => Err(RdiError::keyed_not_found(type_name, key, None)),
431            Err(e) => Err(e),
432        }
433    }
434
435    /// Resolve owned `T` (bypass cache, fresh each call).
436    /// Returns `Err` if not registered or the service is Singleton.
437    pub fn get_owned<T: Send + Sync + 'static>(&self) -> Result<T, RdiError> {
438        let type_name = std::any::type_name::<T>();
439        let tid = TypeId::of::<T>();
440        let entry = self
441            .store
442            .get(&tid)
443            .and_then(|entries| entries.iter().find(|e| e.key.is_none()))
444            .ok_or_else(|| RdiError::not_found(type_name, None))?;
445        if entry.lifetime == ServiceLifetime::Singleton {
446            return Err(RdiError::OwnedNotSupported(type_name));
447        }
448        let arc_any = match std::panic::catch_unwind(AssertUnwindSafe(|| {
449            self.create_owned_any_by_entry(entry)
450        })) {
451            Ok(Some(v)) => v,
452            Ok(None) => return Err(RdiError::not_found(type_name, None)),
453            Err(payload) => return Err(RdiError::from_panic_payload(type_name, payload)),
454        };
455        let arc_t = Self::extract(arc_any).ok_or_else(|| RdiError::not_found(type_name, None))?;
456        Arc::try_unwrap(arc_t).map_err(|_| RdiError::OwnedNotSupported(type_name))
457    }
458
459    /// Resolve owned `T`, returning `None` if not registered or Singleton.
460    pub fn try_get_owned<T: Send + Sync + 'static>(&self) -> Option<T> {
461        self.get_owned().ok()
462    }
463
464    /// Resolve owned keyed `T`.
465    /// Returns `Err` if not found or Singleton.
466    pub fn get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Result<T, RdiError> {
467        let type_name = std::any::type_name::<T>();
468        let tid = TypeId::of::<T>();
469        let entry = self
470            .store
471            .get(&tid)
472            .and_then(|entries| entries.iter().find(|e| e.key.as_deref() == Some(key)))
473            .ok_or_else(|| RdiError::keyed_not_found(type_name, key, None))?;
474        if entry.lifetime == ServiceLifetime::Singleton {
475            return Err(RdiError::OwnedNotSupported(type_name));
476        }
477        let arc_any = match std::panic::catch_unwind(AssertUnwindSafe(|| {
478            self.create_owned_any_by_entry(entry)
479        })) {
480            Ok(Some(v)) => v,
481            Ok(None) => return Err(RdiError::keyed_not_found(type_name, key, None)),
482            Err(payload) => return Err(RdiError::from_panic_payload(type_name, payload)),
483        };
484        let arc_t =
485            Self::extract(arc_any).ok_or_else(|| RdiError::keyed_not_found(type_name, key, None))?;
486        Arc::try_unwrap(arc_t).map_err(|_| RdiError::OwnedNotSupported(type_name))
487    }
488
489    /// Resolve owned keyed `T`, returning `None` if not found or Singleton.
490    pub fn try_get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Option<T> {
491        self.get_keyed_owned(key).ok()
492    }
493
494    /// Return all registered instances of the given type.
495    pub fn get_all<T: ?Sized + Send + Sync + 'static>(&self) -> Vec<Arc<T>> {
496        let tid = TypeId::of::<T>();
497        match self.store.get(&tid) {
498            Some(entries) => entries
499                .iter()
500                .filter_map(|e| {
501                    let arc = self.get_any_by_entry(e)?;
502                    Self::extract(arc)
503                })
504                .collect(),
505            None => Vec::new(),
506        }
507    }
508
509    /// Create a new service scope.
510    ///
511    /// Analogous to `IServiceProvider.CreateScope()` in MEDI.
512    /// Scoped-lifetime services are cached within the returned scope.
513    pub fn scope(self: &Arc<Self>) -> crate::scope::Scope {
514        crate::scope::Scope::new(self.clone())
515    }
516
517    #[allow(dead_code)]
518    fn try_get<T: ?Sized + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
519        self.resolve_optional::<T>().ok().flatten()
520    }
521
522    #[allow(dead_code)]
523    fn try_get_keyed<T: ?Sized + Send + Sync + 'static>(&self, key: &str) -> Option<Arc<T>> {
524        self.resolve_keyed_optional::<T>(key).ok().flatten()
525    }
526
527    /// Resolve `T`, mapping inject/`panic_any(RdiError)` factory failures to [`RdiError`].
528    fn resolve_optional<T: ?Sized + Send + Sync + 'static>(
529        &self,
530    ) -> Result<Option<Arc<T>>, RdiError> {
531        let tid = TypeId::of::<T>();
532        if let Some(entry) = self
533            .store
534            .get(&tid)
535            .and_then(|entries| entries.iter().find(|e| e.key.is_none()))
536        {
537            let arc = self.resolve_entry_catching(entry)?;
538            return Ok(Self::extract(arc));
539        }
540        // Built-in ScopeFactory: any built provider can create scopes.
541        if tid == TypeId::of::<dyn ScopeFactory>() {
542            let Some(p) = self.provider_arc() else {
543                return Ok(None);
544            };
545            let sf: Arc<dyn ScopeFactory> = p;
546            return Ok(Self::extract(Arc::new(sf) as AnyService));
547        }
548        Ok(None)
549    }
550
551    fn resolve_keyed_optional<T: ?Sized + Send + Sync + 'static>(
552        &self,
553        key: &str,
554    ) -> Result<Option<Arc<T>>, RdiError> {
555        let tid = TypeId::of::<T>();
556        let Some(entry) = self
557            .store
558            .get(&tid)
559            .and_then(|entries| entries.iter().find(|e| e.key.as_deref() == Some(key)))
560        else {
561            return Ok(None);
562        };
563        let arc = self.resolve_entry_catching(entry)?;
564        Ok(Self::extract(arc))
565    }
566
567    pub(crate) fn resolve_entry_catching(&self, entry: &ServiceEntry) -> Result<AnyService, RdiError> {
568        match std::panic::catch_unwind(AssertUnwindSafe(|| self.get_any_by_entry(entry))) {
569            Ok(Some(v)) => Ok(v),
570            Ok(None) => Err(RdiError::not_found(entry.type_name, None)),
571            Err(payload) => Err(RdiError::from_panic_payload(entry.type_name, payload)),
572        }
573    }
574
575    pub(crate) fn get_any_by_entry(&self, entry: &ServiceEntry) -> Option<AnyService> {
576        let _guard = match enter_resolve(entry.cache_key, entry.type_name) {
577            Ok(g) => g,
578            Err(e) => std::panic::panic_any(e),
579        };
580        match entry.lifetime {
581            ServiceLifetime::Singleton => {
582                // LazyCache::get_or_init_with:build 阶段已预热的走 fast path,
583                // 未预热的(交叉引用边缘情况)懒执行工厂并缓存。
584                // per-key OnceLock 保证多线程下工厂只执行一次,无 TOCTOU 竞态。
585                // 工厂 panic 时 OnceLock 不缓存(std 行为),下次解析重试。
586                let factory = entry.factory.clone();
587                let resolver = self as &dyn IServiceResolver;
588                Some(self.singleton_cache.get_or_init_with(entry.cache_key, move || {
589                    factory(resolver)
590                }))
591            }
592            ServiceLifetime::Scoped => {
593                // Root scope 缓存:ServiceProvider 即 root scope,
594                // 从根解析 Scoped 服务在 root_scoped_cache 内复用。
595                let factory = entry.factory.clone();
596                let resolver = self as &dyn IServiceResolver;
597                Some(self.root_scoped_cache.get_or_init_with(entry.cache_key, move || {
598                    factory(resolver)
599                }))
600            }
601            ServiceLifetime::Transient => Some((entry.factory)(self)),
602        }
603    }
604
605    /// Bypass cache and invoke the factory fresh (owned resolution only).
606    ///
607    /// - Singleton → `None` (shared singleton cannot be owned).
608    /// - Scoped/Transient → invoke factory directly without touching
609    ///   `singleton_cache` / `root_scoped_cache`. The factory uses `self`
610    ///   (ServiceProvider, i.e. root scope) as resolver, so Scoped deps
611    ///   resolved transitively bind to the root scope (consistent with
612    ///   `get_any_by_entry`'s Scoped root-cache semantics).
613    pub(crate) fn create_owned_any_by_entry(&self, entry: &ServiceEntry) -> Option<AnyService> {
614        match entry.lifetime {
615            ServiceLifetime::Singleton => None,
616            ServiceLifetime::Scoped | ServiceLifetime::Transient => {
617                let _guard = match enter_resolve(entry.cache_key, entry.type_name) {
618                    Ok(g) => g,
619                    Err(e) => std::panic::panic_any(e),
620                };
621                Some((entry.factory)(self as &dyn IServiceResolver))
622            }
623        }
624    }
625
626    /// Extract `Arc<T>` from `Arc<Arc<T>>` stored inside `Arc<dyn Any>`.
627    /// The factory double-wraps: inner `Arc<T>`, outer `Arc<dyn Any>`.
628    pub(crate) fn extract<T: ?Sized + Send + Sync + 'static>(
629        arc: Arc<dyn Any + Send + Sync>,
630    ) -> Option<Arc<T>> {
631        let double: Arc<Arc<T>> = arc.downcast::<Arc<T>>().ok()?;
632        Some(Arc::clone(&*double))
633    }
634
635    /// Find entry by string type_name + variant (for string-based resolution).
636    pub(crate) fn entry_by_str(&self, type_name: &str, variant: &str) -> Option<&ServiceEntry> {
637        let tid = self.type_map.get(type_name)?;
638        self.store
639            .get(tid)?
640            .iter()
641            .find(|e| e.key.as_deref() == Some(variant))
642    }
643
644    /// Cross-DLL safe named service resolution (generic).
645    pub fn get_named<T: Send + Sync + 'static>(&self, name: &str) -> Option<Arc<T>> {
646        self.named
647            .read()
648            .unwrap()
649            .get(name)?
650            .clone()
651            .downcast::<T>()
652            .ok()
653    }
654
655    /// Non-generic named resolution; returns `Arc<dyn Any>` for trait-object dispatch.
656    pub fn get_named_any(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
657        self.named.read().unwrap().get(name).cloned()
658    }
659
660    /// Register a named service for cross-DLL plugin access.
661    pub fn register_named<T: Send + Sync + 'static>(&self, name: &str, service: Arc<T>) {
662        self.named
663            .write()
664            .unwrap()
665            .insert(name.to_string(), service);
666    }
667
668    /// Remove a named service (for plugin unload).
669    pub fn remove_named(&self, name: &str) {
670        self.named.write().unwrap().remove(name);
671    }
672
673    /// Register a named service (for [`IProvider`](crate::bridge::IProvider) trait).
674    pub fn rdi_register_named(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
675        self.named
676            .write()
677            .unwrap()
678            .insert(name.to_string(), service);
679    }
680
681    /// Remove a named service (for [`IProvider`](crate::bridge::IProvider) trait).
682    pub fn rdi_remove_named(&self, name: &str) {
683        self.named.write().unwrap().remove(name);
684    }
685}
686
687impl ScopeFactory for ServiceProvider {
688    fn create_scope(&self) -> crate::scope::Scope {
689        // 通过 self_weak 获取 Arc<Self>(new() / new_async() 已初始化 self_weak)。
690        self.self_weak
691            .get()
692            .and_then(|w| w.upgrade())
693            .map(crate::scope::Scope::new)
694            .expect("ScopeFactory::create_scope: ServiceProvider self_weak not initialized")
695    }
696}
697
698impl IServiceResolver for ServiceProvider {
699    fn get_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
700        let tid = self.type_map.get(key)?;
701        let entry = self.store.get(tid)?.iter().find(|e| e.key.is_none())?;
702        self.get_any_by_entry(entry)
703    }
704    fn get_keyed_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
705        let entry = self.entry_by_str(key, variant)?;
706        self.get_any_by_entry(entry)
707    }
708    fn get_by_type_id(&self, tid: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
709        if let Some(entry) = self.store.get(&tid)?.iter().find(|e| e.key.is_none()) {
710            return self.get_any_by_entry(entry);
711        }
712        if tid == TypeId::of::<dyn ScopeFactory>() {
713            let p = self.provider_arc()?;
714            let sf: Arc<dyn ScopeFactory> = p;
715            return Some(Arc::new(sf) as AnyService);
716        }
717        None
718    }
719    fn get_keyed_by_type_id(
720        &self,
721        tid: TypeId,
722        key: &str,
723    ) -> Option<Arc<dyn Any + Send + Sync>> {
724        let entry = self
725            .store
726            .get(&tid)?
727            .iter()
728            .find(|e| e.key.as_deref() == Some(key))?;
729        self.get_any_by_entry(entry)
730    }
731    fn get_all_any(&self, key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
732        // 复用 type_map → store 路径,遍历某 TypeId 下所有 entry(default + keyed),
733        // 逐个 get_any_by_entry 收集。空注册返回空 Vec,不 panic。
734        let tid = match self.type_map.get(key) {
735            Some(t) => t,
736            None => return Vec::new(),
737        };
738        match self.store.get(tid) {
739            Some(entries) => entries
740                .iter()
741                .filter_map(|e| self.get_any_by_entry(e))
742                .collect(),
743            None => Vec::new(),
744        }
745    }
746    fn get_owned_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
747        let tid = self.type_map.get(key)?;
748        let entry = self.store.get(tid)?.iter().find(|e| e.key.is_none())?;
749        self.create_owned_any_by_entry(entry)
750    }
751    fn get_keyed_owned_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
752        let entry = self.entry_by_str(key, variant)?;
753        self.create_owned_any_by_entry(entry)
754    }
755    fn provider_arc(&self) -> Option<Arc<ServiceProvider>> {
756        self.self_weak.get().and_then(|w| w.upgrade())
757    }
758}
759
760#[cfg(test)]
761mod tests {
762    use crate::collection::ServiceCollection;
763    use std::sync::Arc;
764
765    #[derive(Debug, PartialEq)]
766    struct Calc(i32);
767    #[test]
768    fn optional_missing() {
769        let p = ServiceCollection::new().build().unwrap();
770        assert!(p.get_optional::<i32>().is_none());
771    }
772    #[test]
773    fn all_basic() {
774        let p = ServiceCollection::new()
775            .keyed_singleton("a", |_| Arc::new(Calc(1)))
776            .keyed_singleton("b", |_| Arc::new(Calc(2)))
777            .build()
778            .unwrap();
779        assert_eq!(p.get_all::<Calc>().len(), 2);
780    }
781}