From 9e01cdf341a7866180b3a63d745f3b2d7578d28a Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 23 Oct 2022 18:12:23 +0200 Subject: refactor!: reduce DI container coupling BREAKING CHANGE: You now have to import the DI containers's interfaces to use the DI containers's methods --- src/di_container/blocking/mod.rs | 166 ++++++++++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 36 deletions(-) (limited to 'src/di_container/blocking/mod.rs') diff --git a/src/di_container/blocking/mod.rs b/src/di_container/blocking/mod.rs index f6b64fa..3b9c16e 100644 --- a/src/di_container/blocking/mod.rs +++ b/src/di_container/blocking/mod.rs @@ -5,6 +5,7 @@ //! use std::collections::HashMap; //! use std::error::Error; //! +//! use syrette::di_container::blocking::IDIContainer; //! use syrette::{injectable, DIContainer}; //! //! trait IDatabaseService @@ -61,11 +62,55 @@ use crate::provider::blocking::{IProvider, Providable}; use crate::ptr::SomePtr; pub mod binding; +pub mod prelude; -/// Dependency injection container. +/// Blocking dependency injection container interface. +pub trait IDIContainer: Sized + 'static + details::DIContainerInternals +{ + /// Returns a new [`BindingBuilder`] for the given interface. + fn bind(self: &mut Rc) -> BindingBuilder + where + Interface: 'static + ?Sized; + + /// Returns the type bound with `Interface`. + /// + /// # Errors + /// Will return `Err` if: + /// - No binding for `Interface` exists + /// - Resolving the binding for `Interface` fails + /// - Casting the binding for `Interface` fails + fn get(self: &Rc) -> Result, DIContainerError> + where + Interface: 'static + ?Sized; + + /// Returns the type bound with `Interface` and the specified name. + /// + /// # Errors + /// Will return `Err` if: + /// - No binding for `Interface` with name `name` exists + /// - Resolving the binding for `Interface` fails + /// - Casting the binding for `Interface` fails + fn get_named( + self: &Rc, + name: &'static str, + ) -> Result, DIContainerError> + where + Interface: 'static + ?Sized; + + #[doc(hidden)] + fn get_bound( + self: &Rc, + dependency_history: Vec<&'static str>, + name: Option<&'static str>, + ) -> Result, DIContainerError> + where + Interface: 'static + ?Sized; +} + +/// Blocking dependency injection container. pub struct DIContainer { - bindings: RefCell>, + bindings: RefCell>>, } impl DIContainer @@ -78,38 +123,26 @@ impl DIContainer bindings: RefCell::new(DIContainerBindingMap::new()), }) } +} - /// Returns a new [`BindingBuilder`] for the given interface. +impl IDIContainer for DIContainer +{ #[must_use] - pub fn bind(self: &mut Rc) -> BindingBuilder + fn bind(self: &mut Rc) -> BindingBuilder where Interface: 'static + ?Sized, { - BindingBuilder::::new(self.clone()) + BindingBuilder::::new(self.clone()) } - /// Returns the type bound with `Interface`. - /// - /// # Errors - /// Will return `Err` if: - /// - No binding for `Interface` exists - /// - Resolving the binding for `Interface` fails - /// - Casting the binding for `Interface` fails - pub fn get(self: &Rc) -> Result, DIContainerError> + fn get(self: &Rc) -> Result, DIContainerError> where Interface: 'static + ?Sized, { self.get_bound::(Vec::new(), None) } - /// Returns the type bound with `Interface` and the specified name. - /// - /// # Errors - /// Will return `Err` if: - /// - No binding for `Interface` with name `name` exists - /// - Resolving the binding for `Interface` fails - /// - Casting the binding for `Interface` fails - pub fn get_named( + fn get_named( self: &Rc, name: &'static str, ) -> Result, DIContainerError> @@ -120,7 +153,7 @@ impl DIContainer } #[doc(hidden)] - pub fn get_bound( + fn get_bound( self: &Rc, dependency_history: Vec<&'static str>, name: Option<&'static str>, @@ -133,10 +166,43 @@ impl DIContainer self.handle_binding_providable(binding_providable) } +} + +impl details::DIContainerInternals for DIContainer +{ + fn has_binding(self: &Rc, name: Option<&'static str>) -> bool + where + Interface: ?Sized + 'static, + { + self.bindings.borrow().has::(name) + } + + fn set_binding( + self: &Rc, + name: Option<&'static str>, + provider: Box>, + ) where + Interface: 'static + ?Sized, + { + self.bindings.borrow_mut().set::(name, provider); + } + + fn remove_binding( + self: &Rc, + name: Option<&'static str>, + ) -> Option>> + where + Interface: 'static + ?Sized, + { + self.bindings.borrow_mut().remove::(name) + } +} +impl DIContainer +{ fn handle_binding_providable( self: &Rc, - binding_providable: Providable, + binding_providable: Providable, ) -> Result, DIContainerError> where Interface: 'static + ?Sized, @@ -195,7 +261,7 @@ impl DIContainer self: &Rc, name: Option<&'static str>, dependency_history: Vec<&'static str>, - ) -> Result + ) -> Result, DIContainerError> where Interface: 'static + ?Sized, { @@ -219,6 +285,34 @@ impl DIContainer } } +pub(crate) mod details +{ + use std::rc::Rc; + + use crate::provider::blocking::IProvider; + + pub trait DIContainerInternals + { + fn has_binding(self: &Rc, name: Option<&'static str>) -> bool + where + Interface: ?Sized + 'static; + + fn set_binding( + self: &Rc, + name: Option<&'static str>, + provider: Box>, + ) where + Interface: 'static + ?Sized; + + fn remove_binding( + self: &Rc, + name: Option<&'static str>, + ) -> Option>> + where + Interface: 'static + ?Sized; + } +} + #[cfg(test)] mod tests { @@ -238,13 +332,13 @@ mod tests mock! { Provider {} - impl IProvider for Provider + impl IProvider for Provider { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, - ) -> Result; + ) -> Result, InjectableError>; } } @@ -276,13 +370,13 @@ mod tests mock! { Provider {} - impl IProvider for Provider + impl IProvider for Provider { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, - ) -> Result; + ) -> Result, InjectableError>; } } @@ -314,13 +408,13 @@ mod tests mock! { Provider {} - impl IProvider for Provider + impl IProvider for Provider { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, - ) -> Result; + ) -> Result, InjectableError>; } } @@ -359,13 +453,13 @@ mod tests mock! { Provider {} - impl IProvider for Provider + impl IProvider for Provider { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, - ) -> Result; + ) -> Result, InjectableError>; } } @@ -459,13 +553,13 @@ mod tests mock! { Provider {} - impl IProvider for Provider + impl IProvider for Provider { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, - ) -> Result; + ) -> Result, InjectableError>; } } @@ -556,13 +650,13 @@ mod tests mock! { Provider {} - impl IProvider for Provider + impl IProvider for Provider { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, - ) -> Result; + ) -> Result, InjectableError>; } } -- cgit v1.2.3-18-g5258