ferroui_dependency_injection/
activator_utilities.rs1use crate::*;
6use std::rc::Rc;
7
8type Constructor<S> =
9 Rc<dyn Fn(&dyn IServiceProvider, Option<&ServiceKey>) -> ServiceResult<Rc<S>>>;
10pub struct ObjectFactory<S: ?Sized> {
11 pub(crate) factory: Constructor<S>,
12 pub(crate) dependencies: Vec<Dependency>,
13}
14impl<S: ?Sized> Clone for ObjectFactory<S> {
15 fn clone(&self) -> Self {
16 Self {
17 factory: self.factory.clone(),
18 dependencies: self.dependencies.clone(),
19 }
20 }
21}
22impl<S: ?Sized + 'static> ObjectFactory<S> {
23 pub fn new(
24 dependencies: Vec<Dependency>,
25 factory: impl Fn(&dyn IServiceProvider, Option<&ServiceKey>) -> ServiceResult<Rc<S>> + 'static,
26 ) -> Self {
27 Self {
28 dependencies,
29 factory: Rc::new(factory),
30 }
31 }
32}
33
34pub struct ActivatorUtilities;
38impl ActivatorUtilities {
39 pub fn create_factory<S: ?Sized + 'static>(factory: ObjectFactory<S>) -> ObjectFactory<S> {
40 factory
41 }
42 pub fn create_instance<S: ?Sized + 'static>(
43 provider: &dyn IServiceProvider,
44 factory: &ObjectFactory<S>,
45 ) -> ServiceResult<Rc<S>> {
46 Self::create_keyed_instance(provider, None, factory)
47 }
48 pub fn create_keyed_instance<S: ?Sized + 'static>(
49 provider: &dyn IServiceProvider,
50 key: Option<&ServiceKey>,
51 factory: &ObjectFactory<S>,
52 ) -> ServiceResult<Rc<S>> {
53 provider.ensure_active()?;
54 (factory.factory)(provider, key)
55 }
56 pub fn get_service_or_create_instance<S: ?Sized + 'static>(
57 provider: &dyn IServiceProvider,
58 factory: &ObjectFactory<S>,
59 ) -> ServiceResult<Rc<S>> {
60 match provider.get_service::<S>()? {
61 Some(value) => Ok(value),
62 None => Self::create_instance(provider, factory),
63 }
64 }
65}
66
67#[macro_export]
80macro_rules! service_factory {
81 ($service:ty, || $body:expr) => { $crate::ObjectFactory::<$service>::new(Vec::new(), move |_, _| Ok($body)) };
82 ($service:ty, |$($name:ident : $kind:ident($($args:tt)*)),* $(,)?| $body:expr) => {{
83 let dependencies: Vec<Option<$crate::Dependency>> = vec![$($crate::service_factory!(@dependency $kind($($args)*))),*];
84 $crate::ObjectFactory::<$service>::new(dependencies.iter().flatten().cloned().collect(), move |provider, service_key| {
85 let mut parameters = dependencies.iter();
86 $(let dependency = parameters.next().expect("constructor parameter");
87 let $name = $crate::service_factory!(@resolve provider, service_key, dependency, $kind($($args)*));)*
88 let _ = &mut parameters;
89 let _ = (&provider, &service_key);
90 Ok($body)
91 })
92 }};
93 (@dependency required($t:ty)) => { Some($crate::Dependency::required::<$t>()) };
94 (@dependency optional($t:ty)) => { Some($crate::Dependency::required::<$t>().optional()) };
95 (@dependency all($t:ty)) => { Some($crate::Dependency::required::<$t>().enumerable()) };
96 (@dependency keyed($t:ty, $key:expr)) => { Some($crate::Dependency::keyed::<$t>(Some(($key).into()))) };
97 (@dependency inherited($t:ty)) => { Some($crate::Dependency::inherited::<$t>()) };
98 (@dependency typed_key($t:ty)) => { None::<$crate::Dependency> };
99 (@dependency key()) => { None::<$crate::Dependency> };
100 (@resolve $p:ident, $k:ident, $d:ident, required($t:ty)) => {{ let _ = $d; $crate::ServiceProviderServiceExtensions::get_required_service::<$t>($p)? }};
101 (@resolve $p:ident, $k:ident, $d:ident, optional($t:ty)) => {{ let _ = $d; $crate::ServiceProviderServiceExtensions::get_service::<$t>($p)? }};
102 (@resolve $p:ident, $k:ident, $d:ident, all($t:ty)) => {{ let _ = $d; $crate::ServiceProviderServiceExtensions::get_services::<$t>($p)? }};
103 (@resolve $p:ident, $k:ident, $d:ident, keyed($t:ty, $key:expr)) => {{ let _ = $d; $crate::ServiceProviderServiceExtensions::get_required_keyed_service::<$t>($p, $d.as_ref().expect("keyed parameter").identifier.service_key.as_ref())? }};
104 (@resolve $p:ident, $k:ident, $d:ident, inherited($t:ty)) => {{ let _ = $d; $crate::ServiceProviderServiceExtensions::get_required_keyed_service::<$t>($p, $k)? }};
105 (@resolve $p:ident, $k:ident, $d:ident, typed_key($t:ty)) => {{
106 let _ = $d;
107 $k.and_then(|key| key.downcast_ref::<$t>()).cloned()
108 .ok_or($crate::ServiceError::TypeMismatch($crate::ServiceType::of::<$t>()))?
109 }};
110 (@resolve $p:ident, $k:ident, $d:ident, key()) => {{ let _ = $d; $k.cloned() }};
111}