dependency_injector/
provider.rs1use std::any::TypeId;
6use std::sync::Arc;
7
8pub trait Injectable: Send + Sync + 'static {
25 #[inline]
27 fn type_id_of() -> TypeId
28 where
29 Self: Sized,
30 {
31 TypeId::of::<Self>()
32 }
33
34 #[inline]
36 fn type_name_of() -> &'static str
37 where
38 Self: Sized,
39 {
40 std::any::type_name::<Self>()
41 }
42}
43
44impl<T: Send + Sync + 'static> Injectable for T {}
46
47pub trait Provider: Injectable {}
49impl<T: Injectable> Provider for T {}
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
53pub enum Lifetime {
54 #[default]
56 Singleton,
57
58 Lazy,
60
61 Transient,
63
64 Scoped,
66}
67
68#[derive(Clone)]
70pub struct ProviderRegistration {
71 pub type_id: TypeId,
73 pub type_name: &'static str,
75 pub register_fn: Arc<dyn Fn(&crate::Container) + Send + Sync>,
77}
78
79impl ProviderRegistration {
80 #[inline]
82 pub fn new<T: Injectable>(register_fn: fn(&crate::Container)) -> Self {
83 Self {
84 type_id: TypeId::of::<T>(),
85 type_name: std::any::type_name::<T>(),
86 register_fn: Arc::new(register_fn),
87 }
88 }
89
90 pub fn singleton<T: Injectable + Clone>(value: T) -> Self {
95 Self {
96 type_id: TypeId::of::<T>(),
97 type_name: std::any::type_name::<T>(),
98 register_fn: Arc::new(move |container: &crate::Container| {
99 container.singleton(value.clone());
100 }),
101 }
102 }
103}
104
105impl std::fmt::Debug for ProviderRegistration {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("ProviderRegistration")
108 .field("type_id", &self.type_id)
109 .field("type_name", &self.type_name)
110 .finish()
111 }
112}
113
114#[macro_export]
116macro_rules! provider {
117 ($type:ty, $factory:expr) => {
118 $crate::ProviderRegistration {
119 type_id: std::any::TypeId::of::<$type>(),
120 type_name: std::any::type_name::<$type>(),
121 register_fn: $crate::Arc::new(|container: &$crate::Container| {
122 container.singleton($factory);
123 }),
124 }
125 };
126 (lazy $type:ty, $factory:expr) => {
127 $crate::ProviderRegistration {
128 type_id: std::any::TypeId::of::<$type>(),
129 type_name: std::any::type_name::<$type>(),
130 register_fn: $crate::Arc::new(|container: &$crate::Container| {
131 container.lazy($factory);
132 }),
133 }
134 };
135 (transient $type:ty, $factory:expr) => {
136 $crate::ProviderRegistration {
137 type_id: std::any::TypeId::of::<$type>(),
138 type_name: std::any::type_name::<$type>(),
139 register_fn: $crate::Arc::new(|container: &$crate::Container| {
140 container.transient($factory);
141 }),
142 }
143 };
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149 use crate::Container;
150
151 #[derive(Clone)]
152 struct TestService {
153 value: String,
154 }
155
156 #[test]
157 fn test_singleton_registration_registers_value() {
158 let registration = ProviderRegistration::singleton(TestService {
159 value: "provided".into(),
160 });
161
162 assert_eq!(registration.type_id, TypeId::of::<TestService>());
163
164 let container = Container::new();
166 (registration.register_fn)(&container);
167
168 let service = container.get::<TestService>().unwrap();
169 assert_eq!(service.value, "provided");
170 }
171}