ferrous_di/provider/
context.rs

1//! Resolver context for dependency injection.
2//!
3//! This module contains the ResolverContext type which provides
4//! the interface for factory functions to resolve dependencies.
5
6use crate::traits::{Resolver, ResolverCore};
7
8/// Context passed to factory functions for resolving dependencies.
9///
10/// ResolverContext wraps a resolver (ServiceProvider or Scope) and provides
11/// the interface that factory functions use to access other services. This
12/// allows factory functions to be independent of the specific resolver type.
13///
14/// # Examples
15///
16/// ```
17/// use ferrous_di::{ServiceCollection, Resolver};
18/// use std::sync::Arc;
19///
20/// struct Database { url: String }
21/// struct UserService { db: Arc<Database> }
22///
23/// let mut services = ServiceCollection::new();
24/// services.add_singleton(Database { 
25///     url: "postgres://localhost".to_string() 
26/// });
27/// services.add_transient_factory::<UserService, _>(|resolver| {
28///     // resolver is a ResolverContext that provides access to other services
29///     UserService {
30///         db: resolver.get_required::<Database>(),
31///     }
32/// });
33/// ```
34pub struct ResolverContext<'a> {
35    resolver: &'a dyn ResolverCore,
36}
37
38impl<'a> ResolverContext<'a> {
39    /// Creates a new ResolverContext wrapping the given resolver.
40    pub(crate) fn new<T>(resolver: &'a T) -> Self 
41    where 
42        T: ResolverCore,
43    {
44        Self { resolver }
45    }
46}
47
48impl<'a> ResolverCore for ResolverContext<'a> {
49    fn resolve_any(&self, key: &crate::Key) -> crate::DiResult<crate::registration::AnyArc> {
50        self.resolver.resolve_any(key)
51    }
52    
53    fn resolve_many(&self, key: &crate::Key) -> crate::DiResult<Vec<crate::registration::AnyArc>> {
54        self.resolver.resolve_many(key)
55    }
56
57    fn push_sync_disposer(&self, f: Box<dyn FnOnce() + Send>) {
58        self.resolver.push_sync_disposer(f);
59    }
60
61    fn push_async_disposer(&self, f: Box<dyn FnOnce() -> crate::internal::BoxFutureUnit + Send>) {
62        self.resolver.push_async_disposer(f);
63    }
64}
65
66impl<'a> Resolver for ResolverContext<'a> {
67    fn register_disposer<T>(&self, service: std::sync::Arc<T>)
68    where
69        T: crate::traits::Dispose + 'static,
70    {
71        self.resolver.push_sync_disposer(Box::new(move || service.dispose()));
72    }
73
74    fn register_async_disposer<T>(&self, service: std::sync::Arc<T>)
75    where
76        T: crate::traits::AsyncDispose + 'static,
77    {
78        self.resolver.push_async_disposer(Box::new(move || {
79            let service = service.clone();
80            Box::pin(async move { service.dispose().await })
81        }));
82    }
83}