Skip to main content

ferroui_dependency_injection/
service_collection.rs

1//! `ServiceCollection.cs`, `IServiceCollection.cs`, `ServiceCollectionServiceExtensions.cs`,
2//! `ServiceCollectionKeyedServiceExtensions.cs`, `Extensions/ServiceCollectionDescriptorExtensions.cs`
3//! and `ServiceCollectionContainerBuilderExtensions.cs`.
4
5use crate::*;
6use std::rc::Rc;
7
8/// Ordered registrations; building a provider snapshots this collection.
9#[derive(Clone, Default)]
10pub struct ServiceCollection {
11    descriptors: Vec<ServiceDescriptor>,
12    read_only: bool,
13}
14pub trait IServiceCollection {
15    fn descriptors(&self) -> &[ServiceDescriptor];
16    fn add(&mut self, descriptor: ServiceDescriptor) -> &mut Self;
17}
18impl IServiceCollection for ServiceCollection {
19    fn descriptors(&self) -> &[ServiceDescriptor] {
20        &self.descriptors
21    }
22    fn add(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
23        self.add(descriptor)
24    }
25}
26impl ServiceCollection {
27    pub fn new() -> Self {
28        Self::default()
29    }
30    pub fn descriptors(&self) -> &[ServiceDescriptor] {
31        &self.descriptors
32    }
33    pub fn len(&self) -> usize {
34        self.descriptors.len()
35    }
36    pub fn is_empty(&self) -> bool {
37        self.descriptors.is_empty()
38    }
39    pub fn is_read_only(&self) -> bool {
40        self.read_only
41    }
42    pub fn make_read_only(&mut self) {
43        self.read_only = true;
44    }
45    // Deviation (DEVIATIONS.md, Dependency injection): upstream throws InvalidOperationException
46    // for a change of a read-only collection; a programming error panics here.
47    fn ensure_mutable(&self) {
48        assert!(!self.read_only, "The service collection is read-only");
49    }
50    pub fn add(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
51        self.ensure_mutable();
52        self.descriptors.push(descriptor);
53        self
54    }
55    pub fn add_sequence(
56        &mut self,
57        descriptors: impl IntoIterator<Item = ServiceDescriptor>,
58    ) -> &mut Self {
59        self.ensure_mutable();
60        self.descriptors.extend(descriptors);
61        self
62    }
63    pub fn insert(&mut self, index: usize, descriptor: ServiceDescriptor) {
64        self.ensure_mutable();
65        self.descriptors.insert(index, descriptor);
66    }
67    pub fn remove_at(&mut self, index: usize) -> ServiceDescriptor {
68        self.ensure_mutable();
69        self.descriptors.remove(index)
70    }
71    pub fn clear(&mut self) {
72        self.ensure_mutable();
73        self.descriptors.clear();
74    }
75    pub fn try_add(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
76        self.ensure_mutable();
77        if !self
78            .descriptors
79            .iter()
80            .any(|d| d.identifier == descriptor.identifier)
81        {
82            self.add(descriptor);
83        }
84        self
85    }
86    pub fn try_add_enumerable(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
87        self.ensure_mutable();
88        let implementation = descriptor
89            .implementation_type
90            .expect("TryAddEnumerable needs with_implementation::<I>()");
91        assert!(
92            implementation != descriptor.service_type()
93                && implementation != ServiceType::of::<dyn std::any::Any>(),
94            "Implementation type is indistinguishable from the service type"
95        );
96        if !self.descriptors.iter().any(|d| {
97            d.identifier == descriptor.identifier && d.implementation_type == Some(implementation)
98        }) {
99            self.add(descriptor);
100        }
101        self
102    }
103    /// Removes the first matching registration, then appends the replacement, as upstream.
104    pub fn replace(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
105        self.ensure_mutable();
106        if let Some(i) = self
107            .descriptors
108            .iter()
109            .position(|d| d.identifier == descriptor.identifier)
110        {
111            self.descriptors.remove(i);
112        }
113        self.add(descriptor)
114    }
115    pub fn remove_all<S: ?Sized + 'static>(&mut self) -> &mut Self {
116        self.remove_all_keyed::<S>(None)
117    }
118    pub fn remove_all_keyed<S: ?Sized + 'static>(&mut self, key: Option<ServiceKey>) -> &mut Self {
119        self.ensure_mutable();
120        let id = ServiceIdentifier::keyed::<S>(key);
121        self.descriptors.retain(|d| d.identifier != id);
122        self
123    }
124    pub fn iter(&self) -> std::slice::Iter<'_, ServiceDescriptor> {
125        self.descriptors.iter()
126    }
127    pub fn contains(&self, descriptor: &ServiceDescriptor) -> bool {
128        self.index_of(descriptor).is_some()
129    }
130    pub fn index_of(&self, descriptor: &ServiceDescriptor) -> Option<usize> {
131        self.descriptors
132            .iter()
133            .position(|d| Rc::ptr_eq(&d.identity, &descriptor.identity))
134    }
135    pub fn remove(&mut self, descriptor: &ServiceDescriptor) -> bool {
136        self.ensure_mutable();
137        if let Some(index) = self.index_of(descriptor) {
138            self.descriptors.remove(index);
139            true
140        } else {
141            false
142        }
143    }
144    pub fn copy_to(&self, target: &mut [ServiceDescriptor], index: usize) {
145        target[index..index + self.len()].clone_from_slice(&self.descriptors);
146    }
147    pub fn build_service_provider(
148        &self,
149        options: ServiceProviderOptions,
150    ) -> ServiceResult<ServiceProvider> {
151        ServiceProvider::build(self.descriptors.clone(), options)
152    }
153    pub fn add_singleton_instance<S: ?Sized + 'static>(&mut self, value: Rc<S>) -> &mut Self {
154        self.add(ServiceDescriptor::instance(value))
155    }
156    pub fn add_keyed_singleton_instance<S: ?Sized + 'static>(
157        &mut self,
158        key: Option<ServiceKey>,
159        value: Rc<S>,
160    ) -> &mut Self {
161        self.add(ServiceDescriptor::instance(value).with_key(key))
162    }
163}
164macro_rules! registrations {
165    ($add:ident, $keyed:ident, $lifetime:ident) => {
166        impl ServiceCollection {
167            pub fn $add<S: ?Sized + 'static, F>(&mut self, factory: F) -> &mut Self
168            where
169                F: Fn(&ServiceProvider) -> ServiceResult<Rc<S>> + 'static,
170            {
171                self.add(ServiceDescriptor::new(ServiceLifetime::$lifetime, factory))
172            }
173            pub fn $keyed<S: ?Sized + 'static, F>(
174                &mut self,
175                key: Option<ServiceKey>,
176                factory: F,
177            ) -> &mut Self
178            where
179                F: Fn(&ServiceProvider, Option<&ServiceKey>) -> ServiceResult<Rc<S>> + 'static,
180            {
181                self.add(ServiceDescriptor::keyed(
182                    ServiceLifetime::$lifetime,
183                    key,
184                    factory,
185                ))
186            }
187        }
188    };
189}
190registrations!(add_singleton, add_keyed_singleton, Singleton);
191registrations!(add_scoped, add_keyed_scoped, Scoped);
192registrations!(add_transient, add_keyed_transient, Transient);
193
194impl std::ops::Index<usize> for ServiceCollection {
195    type Output = ServiceDescriptor;
196    fn index(&self, index: usize) -> &Self::Output {
197        &self.descriptors[index]
198    }
199}
200impl std::ops::IndexMut<usize> for ServiceCollection {
201    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
202        self.ensure_mutable();
203        &mut self.descriptors[index]
204    }
205}
206impl<'a> IntoIterator for &'a ServiceCollection {
207    type Item = &'a ServiceDescriptor;
208    type IntoIter = std::slice::Iter<'a, ServiceDescriptor>;
209    fn into_iter(self) -> Self::IntoIter {
210        self.iter()
211    }
212}