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