Skip to main content

rust_dix/
provider.rs

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