Skip to main content

rust_dix/
wrapper.rs

1use crate::entry::IServiceResolver;
2use crate::error::RdiError;
3use crate::provider::ServiceProvider;
4use std::any::{Any, TypeId};
5use std::sync::Arc;
6
7pub struct ServiceProviderWrapper {
8    child: Arc<ServiceProvider>,
9    root: Arc<ServiceProvider>,
10}
11
12impl ServiceProviderWrapper {
13    pub fn new(child: Arc<ServiceProvider>, root: Arc<ServiceProvider>) -> Arc<Self> {
14        Arc::new(Self { child, root })
15    }
16    pub fn child(&self) -> &Arc<ServiceProvider> {
17        &self.child
18    }
19    pub fn root(&self) -> &Arc<ServiceProvider> {
20        &self.root
21    }
22
23    pub fn get<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, RdiError> {
24        let type_name = std::any::type_name::<T>();
25        self.try_get::<T>()
26            .ok_or_else(|| RdiError::not_found(type_name, None))
27    }
28    pub fn get_optional<T: ?Sized + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
29        self.try_get::<T>()
30    }
31    pub fn get_keyed<T: ?Sized + Send + Sync + 'static>(&self, key: &str) -> Result<Arc<T>, RdiError> {
32        let type_name = std::any::type_name::<T>();
33        self.try_get_keyed::<T>(key)
34            .ok_or_else(|| RdiError::keyed_not_found(type_name, key, None))
35    }
36    pub fn get_all<T: ?Sized + Send + Sync + 'static>(&self) -> Vec<Arc<T>> {
37        let mut r = self.child.get_all::<T>();
38        r.extend(self.root.get_all::<T>());
39        r
40    }
41    pub fn get_named<T: Send + Sync + 'static>(&self, name: &str) -> Option<Arc<T>> {
42        self.child
43            .get_named::<T>(name)
44            .or_else(|| self.root.get_named::<T>(name))
45    }
46    pub fn get_named_any(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
47        self.child
48            .get_named_any(name)
49            .or_else(|| self.root.get_named_any(name))
50    }
51
52    /// Resolve owned `T` (bypass cache, fresh each call). Child-first, root-fallback.
53    /// Returns `Err` if not registered or the service is Singleton.
54    pub fn get_owned<T: Send + Sync + 'static>(&self) -> Result<T, RdiError> {
55        let type_name = std::any::type_name::<T>();
56        self.try_get_owned::<T>()
57            .ok_or_else(|| RdiError::not_found(type_name, None))
58    }
59    /// Resolve owned `T`, returning `None` if not registered or Singleton.
60    pub fn try_get_owned<T: Send + Sync + 'static>(&self) -> Option<T> {
61        let arc_any = IServiceResolver::get_owned_any(self.child.as_ref(), std::any::type_name::<T>())
62            .or_else(|| {
63                IServiceResolver::get_owned_any(self.root.as_ref(), std::any::type_name::<T>())
64            })?;
65        let arc_t = crate::provider::ServiceProvider::extract::<T>(arc_any)?;
66        Arc::try_unwrap(arc_t).ok()
67    }
68    /// Resolve owned keyed `T`. Child-first, root-fallback.
69    pub fn get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Result<T, RdiError> {
70        let type_name = std::any::type_name::<T>();
71        self.try_get_keyed_owned::<T>(key)
72            .ok_or_else(|| RdiError::keyed_not_found(type_name, key, None))
73    }
74    /// Resolve owned keyed `T`, returning `None` if not found or Singleton.
75    pub fn try_get_keyed_owned<T: Send + Sync + 'static>(&self, key: &str) -> Option<T> {
76        let arc_any =
77            IServiceResolver::get_keyed_owned_any(self.child.as_ref(), std::any::type_name::<T>(), key)
78                .or_else(|| {
79                    IServiceResolver::get_keyed_owned_any(self.root.as_ref(), std::any::type_name::<T>(), key)
80                })?;
81        let arc_t = crate::provider::ServiceProvider::extract::<T>(arc_any)?;
82        Arc::try_unwrap(arc_t).ok()
83    }
84
85    /// Resolve an async service by type. Child-first, root-fallback.
86    pub async fn get_async<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, RdiError> {
87        match self.child.get_async::<T>().await {
88            Ok(svc) => Ok(svc),
89            Err(_) => self.root.get_async::<T>().await,
90        }
91    }
92    /// Resolve an async keyed service. Child-first, root-fallback.
93    pub async fn get_keyed_async<T: ?Sized + Send + Sync + 'static>(
94        &self,
95        key: &str,
96    ) -> Result<Arc<T>, RdiError> {
97        match self.child.get_keyed_async::<T>(key).await {
98            Ok(svc) => Ok(svc),
99            Err(_) => self.root.get_keyed_async::<T>(key).await,
100        }
101    }
102
103    fn try_get<T: ?Sized + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
104        self.child
105            .get_optional::<T>()
106            .or_else(|| self.root.get_optional::<T>())
107    }
108
109    fn try_get_keyed<T: ?Sized + Send + Sync + 'static>(&self, key: &str) -> Option<Arc<T>> {
110        // Delegate to IServiceResolver which goes through the cache properly.
111        IServiceResolver::get_keyed_any(self.child.as_ref(), std::any::type_name::<T>(), key)
112            .or_else(|| {
113                IServiceResolver::get_keyed_any(self.root.as_ref(), std::any::type_name::<T>(), key)
114            })
115            .and_then(|arc| crate::provider::ServiceProvider::extract(arc))
116    }
117}
118
119impl IServiceResolver for ServiceProviderWrapper {
120    fn get_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
121        IServiceResolver::get_any(self.child.as_ref(), key)
122            .or_else(|| IServiceResolver::get_any(self.root.as_ref(), key))
123    }
124    fn get_keyed_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
125        IServiceResolver::get_keyed_any(self.child.as_ref(), key, variant)
126            .or_else(|| IServiceResolver::get_keyed_any(self.root.as_ref(), key, variant))
127    }
128    fn get_by_type_id(&self, tid: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
129        self.child
130            .get_by_type_id(tid)
131            .or_else(|| self.root.get_by_type_id(tid))
132    }
133    fn get_keyed_by_type_id(
134        &self,
135        tid: TypeId,
136        key: &str,
137    ) -> Option<Arc<dyn Any + Send + Sync>> {
138        self.child
139            .get_keyed_by_type_id(tid, key)
140            .or_else(|| self.root.get_keyed_by_type_id(tid, key))
141    }
142    fn get_all_any(&self, key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
143        // 合并 child + root:与 inherent `get_all` 的 child-then-root 顺序一致。
144        let mut result = IServiceResolver::get_all_any(self.child.as_ref(), key);
145        result.extend(IServiceResolver::get_all_any(self.root.as_ref(), key));
146        result
147    }
148    fn get_owned_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
149        IServiceResolver::get_owned_any(self.child.as_ref(), key)
150            .or_else(|| IServiceResolver::get_owned_any(self.root.as_ref(), key))
151    }
152    fn get_keyed_owned_any(
153        &self,
154        key: &str,
155        variant: &str,
156    ) -> Option<Arc<dyn Any + Send + Sync>> {
157        IServiceResolver::get_keyed_owned_any(self.child.as_ref(), key, variant)
158            .or_else(|| IServiceResolver::get_keyed_owned_any(self.root.as_ref(), key, variant))
159    }
160    fn provider_arc(&self) -> Option<Arc<ServiceProvider>> {
161        Some(Arc::clone(&self.child))
162    }
163}
164
165impl ServiceProviderWrapper {
166    /// Register a named service (for [`IProvider`](crate::bridge::IProvider) trait).
167    pub fn rdi_register_named(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
168        self.child.rdi_register_named(name, service);
169    }
170
171    /// Remove a named service (for [`IProvider`](crate::bridge::IProvider) trait).
172    pub fn rdi_remove_named(&self, name: &str) {
173        self.child.rdi_remove_named(name);
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use crate::collection::ServiceCollection;
181    #[derive(Debug, PartialEq)]
182    struct PO;
183    #[derive(Debug, PartialEq)]
184    struct RO {
185        v: i32,
186    }
187    #[derive(Debug, PartialEq)]
188    struct B {
189        s: String,
190    }
191    #[test]
192    fn child_prio() {
193        let r = ServiceCollection::new()
194            .singleton(|_| Arc::new(B { s: "root".into() }))
195            .build()
196            .unwrap();
197        let c = ServiceCollection::new()
198            .singleton(|_| Arc::new(B { s: "child".into() }))
199            .build()
200            .unwrap();
201        let w = ServiceProviderWrapper::new(c, r);
202        assert_eq!(w.get::<B>().unwrap().s, "child");
203    }
204    #[test]
205    fn root_fallback() {
206        let r = ServiceCollection::new()
207            .singleton(|_| Arc::new(RO { v: 42 }))
208            .build()
209            .unwrap();
210        let c = ServiceCollection::new().build().unwrap();
211        let w = ServiceProviderWrapper::new(c, r);
212        assert_eq!(w.get::<RO>().unwrap().v, 42);
213    }
214    #[test]
215    fn child_invisible() {
216        let r = ServiceCollection::new().build().unwrap();
217        let c = ServiceCollection::new()
218            .singleton(|_| Arc::new(PO))
219            .build()
220            .unwrap();
221        let _w = ServiceProviderWrapper::new(c, r.clone());
222        assert!(r.get_optional::<PO>().is_none());
223    }
224}