diff options
Diffstat (limited to 'src/di_container/blocking/binding')
-rw-r--r-- | src/di_container/blocking/binding/builder.rs | 273 | ||||
-rw-r--r-- | src/di_container/blocking/binding/scope_configurator.rs | 45 | ||||
-rw-r--r-- | src/di_container/blocking/binding/when_configurator.rs | 46 |
3 files changed, 174 insertions, 190 deletions
diff --git a/src/di_container/blocking/binding/builder.rs b/src/di_container/blocking/binding/builder.rs index 8e15f0c..e1c1561 100644 --- a/src/di_container/blocking/binding/builder.rs +++ b/src/di_container/blocking/binding/builder.rs @@ -1,4 +1,6 @@ -//! Binding builder for types inside of a [`DIContainer`]. +//! Binding builder for types inside of a [`IDIContainer`]. +//! +//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer use std::any::type_name; use std::marker::PhantomData; use std::rc::Rc; @@ -6,24 +8,28 @@ use std::rc::Rc; use crate::di_container::blocking::binding::scope_configurator::BindingScopeConfigurator; #[cfg(feature = "factory")] use crate::di_container::blocking::binding::when_configurator::BindingWhenConfigurator; -use crate::di_container::blocking::DIContainer; +use crate::di_container::blocking::IDIContainer; use crate::errors::di_container::BindingBuilderError; use crate::interfaces::injectable::Injectable; -/// Binding builder for type `Interface` inside a [`DIContainer`]. -pub struct BindingBuilder<Interface> +/// Binding builder for type `Interface` inside a [`IDIContainer`]. +/// +/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer +pub struct BindingBuilder<Interface, DIContainerType> where Interface: 'static + ?Sized, + DIContainerType: IDIContainer, { - di_container: Rc<DIContainer>, + di_container: Rc<DIContainerType>, interface_phantom: PhantomData<Interface>, } -impl<Interface> BindingBuilder<Interface> +impl<Interface, DIContainerType> BindingBuilder<Interface, DIContainerType> where Interface: 'static + ?Sized, + DIContainerType: IDIContainer, { - pub(crate) fn new(di_container: Rc<DIContainer>) -> Self + pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self { Self { di_container, @@ -32,13 +38,13 @@ where } /// Creates a binding of type `Interface` to type `Implementation` inside of the - /// associated [`DIContainer`]. + /// associated [`IDIContainer`]. /// /// The scope of the binding is transient. But that can be changed by using the /// returned [`BindingScopeConfigurator`] /// /// # Errors - /// Will return Err if the associated [`DIContainer`] already have a binding for + /// Will return Err if the associated [`IDIContainer`] already have a binding for /// the interface. /// /// # Examples @@ -46,6 +52,7 @@ where /// # use std::error::Error; /// # /// # use syrette::{DIContainer, injectable}; + /// # use syrette::di_container::blocking::IDIContainer; /// # /// # trait Foo {} /// # @@ -70,16 +77,19 @@ where /// # Ok(()) /// # } /// ``` + /// + /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer pub fn to<Implementation>( &self, - ) -> Result<BindingScopeConfigurator<Interface, Implementation>, BindingBuilderError> + ) -> Result< + BindingScopeConfigurator<Interface, Implementation, DIContainerType>, + BindingBuilderError, + > where - Implementation: Injectable, + Implementation: Injectable<DIContainerType>, { { - let bindings = self.di_container.bindings.borrow(); - - if bindings.has::<Interface>(None) { + if self.di_container.has_binding::<Interface>(None) { return Err(BindingBuilderError::BindingAlreadyExists(type_name::< Interface, >( @@ -96,10 +106,10 @@ where } /// Creates a binding of factory type `Interface` to a factory inside of the - /// associated [`DIContainer`]. + /// associated [`IDIContainer`]. /// /// # Errors - /// Will return Err if the associated [`DIContainer`] already have a binding for + /// Will return Err if the associated [`IDIContainer`] already have a binding for /// the interface. /// /// # Examples @@ -108,6 +118,7 @@ where /// # /// # use syrette::{DIContainer, factory}; /// # use syrette::ptr::TransientPtr; + /// # use syrette::di_container::blocking::IDIContainer; /// # /// # trait ICustomerID {} /// # trait ICustomer {} @@ -158,36 +169,31 @@ where /// # Ok(()) /// # } /// ``` + /// + /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer #[cfg(feature = "factory")] #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))] pub fn to_factory<Args, Return, Func>( &self, factory_func: &'static Func, - ) -> Result<BindingWhenConfigurator<Interface>, BindingBuilderError> + ) -> Result<BindingWhenConfigurator<Interface, DIContainerType>, BindingBuilderError> where Args: 'static, Return: 'static + ?Sized, Interface: Fn<Args, Output = crate::ptr::TransientPtr<Return>>, - Func: Fn<(std::rc::Rc<DIContainer>,), Output = Box<Interface>>, + Func: Fn<(std::rc::Rc<DIContainerType>,), Output = Box<Interface>>, { use crate::castable_factory::blocking::CastableFactory; - { - let bindings = self.di_container.bindings.borrow(); - - if bindings.has::<Interface>(None) { - return Err(BindingBuilderError::BindingAlreadyExists(type_name::< - Interface, - >( - ))); - } + if self.di_container.has_binding::<Interface>(None) { + return Err(BindingBuilderError::BindingAlreadyExists(type_name::< + Interface, + >())); } - let mut bindings_mut = self.di_container.bindings.borrow_mut(); - let factory_impl = CastableFactory::new(factory_func); - bindings_mut.set::<Interface>( + self.di_container.set_binding::<Interface>( None, Box::new(crate::provider::blocking::FactoryProvider::new( crate::ptr::FactoryPtr::new(factory_impl), @@ -199,10 +205,10 @@ where } /// Creates a binding of type `Interface` to a factory that takes no arguments - /// inside of the associated [`DIContainer`]. + /// inside of the associated [`IDIContainer`]. /// /// # Errors - /// Will return Err if the associated [`DIContainer`] already have a binding for + /// Will return Err if the associated [`IDIContainer`] already have a binding for /// the interface. /// /// # Examples @@ -211,6 +217,7 @@ where /// # /// # use syrette::{DIContainer, factory}; /// # use syrette::ptr::TransientPtr; + /// # use syrette::di_container::blocking::IDIContainer; /// # /// # trait IBuffer {} /// # @@ -248,16 +255,18 @@ where /// # Ok(()) /// # } /// ``` + /// + /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer #[cfg(feature = "factory")] #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))] pub fn to_default_factory<Return, FactoryFunc>( &self, factory_func: &'static FactoryFunc, - ) -> Result<BindingWhenConfigurator<Interface>, BindingBuilderError> + ) -> Result<BindingWhenConfigurator<Interface, DIContainerType>, BindingBuilderError> where Return: 'static + ?Sized, FactoryFunc: Fn< - (Rc<DIContainer>,), + (Rc<DIContainerType>,), Output = crate::ptr::TransientPtr< dyn Fn<(), Output = crate::ptr::TransientPtr<Return>>, >, @@ -265,22 +274,15 @@ where { use crate::castable_factory::blocking::CastableFactory; - { - let bindings = self.di_container.bindings.borrow(); - - if bindings.has::<Interface>(None) { - return Err(BindingBuilderError::BindingAlreadyExists(type_name::< - Interface, - >( - ))); - } + if self.di_container.has_binding::<Interface>(None) { + return Err(BindingBuilderError::BindingAlreadyExists(type_name::< + Interface, + >())); } - let mut bindings_mut = self.di_container.bindings.borrow_mut(); - let factory_impl = CastableFactory::new(factory_func); - bindings_mut.set::<Interface>( + self.di_container.set_binding::<Interface>( None, Box::new(crate::provider::blocking::FactoryProvider::new( crate::ptr::FactoryPtr::new(factory_impl), @@ -297,92 +299,34 @@ mod tests { use std::error::Error; + use mockall::predicate::eq; + use super::*; - use crate::ptr::TransientPtr; - use crate::test_utils::subjects; + use crate::test_utils::{mocks, subjects}; #[test] fn can_bind_to() -> Result<(), Box<dyn Error>> { - let mut di_container = DIContainer::new(); + let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); - assert_eq!(di_container.bindings.borrow().count(), 0); + mock_di_container + .expect_has_binding::<dyn subjects::INumber>() + .with(eq(None)) + .return_once(|_name| false) + .once(); - di_container - .bind::<dyn subjects::IUserManager>() - .to::<subjects::UserManager>()?; + mock_di_container + .expect_set_binding::<dyn subjects::INumber>() + .withf(|name, _provider| name.is_none()) + .return_once(|_name, _provider| ()) + .once(); - assert_eq!(di_container.bindings.borrow().count(), 1); + let binding_builder = BindingBuilder::< + dyn subjects::INumber, + mocks::blocking_di_container::MockDIContainer, + >::new(Rc::new(mock_di_container)); - Ok(()) - } - - #[test] - fn can_bind_to_transient() -> Result<(), Box<dyn Error>> - { - let mut di_container = DIContainer::new(); - - assert_eq!(di_container.bindings.borrow().count(), 0); - - di_container - .bind::<dyn subjects::IUserManager>() - .to::<subjects::UserManager>()? - .in_transient_scope(); - - assert_eq!(di_container.bindings.borrow().count(), 1); - - Ok(()) - } - - #[test] - fn can_bind_to_transient_when_named() -> Result<(), Box<dyn Error>> - { - let mut di_container = DIContainer::new(); - - assert_eq!(di_container.bindings.borrow().count(), 0); - - di_container - .bind::<dyn subjects::IUserManager>() - .to::<subjects::UserManager>()? - .in_transient_scope() - .when_named("regular")?; - - assert_eq!(di_container.bindings.borrow().count(), 1); - - Ok(()) - } - - #[test] - fn can_bind_to_singleton() -> Result<(), Box<dyn Error>> - { - let mut di_container = DIContainer::new(); - - assert_eq!(di_container.bindings.borrow().count(), 0); - - di_container - .bind::<dyn subjects::IUserManager>() - .to::<subjects::UserManager>()? - .in_singleton_scope()?; - - assert_eq!(di_container.bindings.borrow().count(), 1); - - Ok(()) - } - - #[test] - fn can_bind_to_singleton_when_named() -> Result<(), Box<dyn Error>> - { - let mut di_container = DIContainer::new(); - - assert_eq!(di_container.bindings.borrow().count(), 0); - - di_container - .bind::<dyn subjects::IUserManager>() - .to::<subjects::UserManager>()? - .in_singleton_scope()? - .when_named("cool")?; - - assert_eq!(di_container.bindings.borrow().count(), 1); + binding_builder.to::<subjects::Number>()?; Ok(()) } @@ -393,57 +337,80 @@ mod tests { use crate as syrette; use crate::factory; + use crate::ptr::TransientPtr; #[factory] - type IUserManagerFactory = dyn Fn() -> dyn subjects::IUserManager; + type IUserManagerFactory = dyn Fn(i32, String) -> dyn subjects::IUserManager; - let mut di_container = DIContainer::new(); + let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); - assert_eq!(di_container.bindings.borrow().count(), 0); + mock_di_container + .expect_has_binding::<IUserManagerFactory>() + .with(eq(None)) + .return_once(|_name| false) + .once(); - di_container - .bind::<IUserManagerFactory>() - .to_factory(&|_| { - Box::new(move || { - let user_manager: TransientPtr<dyn subjects::IUserManager> = - TransientPtr::new(subjects::UserManager::new()); + mock_di_container + .expect_set_binding::<IUserManagerFactory>() + .withf(|name, _provider| name.is_none()) + .return_once(|_name, _provider| ()) + .once(); - user_manager - }) - })?; + let binding_builder = BindingBuilder::< + IUserManagerFactory, + mocks::blocking_di_container::MockDIContainer, + >::new(Rc::new(mock_di_container)); - assert_eq!(di_container.bindings.borrow().count(), 1); + binding_builder.to_factory(&|_| { + Box::new(move |_num, _text| { + let user_manager: TransientPtr<dyn subjects::IUserManager> = + TransientPtr::new(subjects::UserManager::new()); + + user_manager + }) + })?; Ok(()) } #[test] #[cfg(feature = "factory")] - fn can_bind_to_factory_when_named() -> Result<(), Box<dyn Error>> + fn can_bind_to_default_factory() -> Result<(), Box<dyn Error>> { + use syrette_macros::declare_default_factory; + use crate as syrette; - use crate::factory; + use crate::ptr::TransientPtr; - #[factory] - type IUserManagerFactory = dyn Fn() -> dyn subjects::IUserManager; + declare_default_factory!(dyn subjects::IUserManager); + + let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); - let mut di_container = DIContainer::new(); + mock_di_container + .expect_has_binding::<dyn subjects::IUserManager>() + .with(eq(None)) + .return_once(|_name| false) + .once(); - assert_eq!(di_container.bindings.borrow().count(), 0); + mock_di_container + .expect_set_binding::<dyn subjects::IUserManager>() + .withf(|name, _provider| name.is_none()) + .return_once(|_name, _provider| ()) + .once(); - di_container - .bind::<IUserManagerFactory>() - .to_factory(&|_| { - Box::new(move || { - let user_manager: TransientPtr<dyn subjects::IUserManager> = - TransientPtr::new(subjects::UserManager::new()); + let binding_builder = BindingBuilder::< + dyn subjects::IUserManager, + mocks::blocking_di_container::MockDIContainer, + >::new(Rc::new(mock_di_container)); - user_manager - }) - })? - .when_named("awesome")?; + binding_builder.to_default_factory(&|_| { + Box::new(move || { + let user_manager: TransientPtr<dyn subjects::IUserManager> = + TransientPtr::new(subjects::UserManager::new()); - assert_eq!(di_container.bindings.borrow().count(), 1); + user_manager + }) + })?; Ok(()) } diff --git a/src/di_container/blocking/binding/scope_configurator.rs b/src/di_container/blocking/binding/scope_configurator.rs index 09897b6..5553415 100644 --- a/src/di_container/blocking/binding/scope_configurator.rs +++ b/src/di_container/blocking/binding/scope_configurator.rs @@ -1,31 +1,38 @@ -//! Scope configurator for a binding for types inside of a [`DIContainer`]. +//! Scope configurator for a binding for types inside of a [`IDIContainer`]. +//! +//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer use std::marker::PhantomData; use std::rc::Rc; use crate::di_container::blocking::binding::when_configurator::BindingWhenConfigurator; -use crate::di_container::blocking::DIContainer; +use crate::di_container::blocking::IDIContainer; use crate::errors::di_container::BindingScopeConfiguratorError; use crate::interfaces::injectable::Injectable; use crate::provider::blocking::{SingletonProvider, TransientTypeProvider}; use crate::ptr::SingletonPtr; -/// Scope configurator for a binding for type 'Interface' inside a [`DIContainer`]. -pub struct BindingScopeConfigurator<Interface, Implementation> +/// Scope configurator for a binding for type 'Interface' inside a [`IDIContainer`]. +/// +/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer +pub struct BindingScopeConfigurator<Interface, Implementation, DIContainerType> where Interface: 'static + ?Sized, - Implementation: Injectable, + Implementation: Injectable<DIContainerType>, + DIContainerType: IDIContainer, { - di_container: Rc<DIContainer>, + di_container: Rc<DIContainerType>, interface_phantom: PhantomData<Interface>, implementation_phantom: PhantomData<Implementation>, } -impl<Interface, Implementation> BindingScopeConfigurator<Interface, Implementation> +impl<Interface, Implementation, DIContainerType> + BindingScopeConfigurator<Interface, Implementation, DIContainerType> where Interface: 'static + ?Sized, - Implementation: Injectable, + Implementation: Injectable<DIContainerType>, + DIContainerType: IDIContainer, { - pub(crate) fn new(di_container: Rc<DIContainer>) -> Self + pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self { Self { di_container, @@ -38,13 +45,13 @@ where /// /// This is the default. #[allow(clippy::must_use_candidate)] - pub fn in_transient_scope(&self) -> BindingWhenConfigurator<Interface> + pub fn in_transient_scope( + &self, + ) -> BindingWhenConfigurator<Interface, DIContainerType> { - let mut bindings_mut = self.di_container.bindings.borrow_mut(); - - bindings_mut.set::<Interface>( + self.di_container.set_binding::<Interface>( None, - Box::new(TransientTypeProvider::<Implementation>::new()), + Box::new(TransientTypeProvider::<Implementation, DIContainerType>::new()), ); BindingWhenConfigurator::new(self.di_container.clone()) @@ -56,16 +63,18 @@ where /// Will return Err if resolving the implementation fails. pub fn in_singleton_scope( &self, - ) -> Result<BindingWhenConfigurator<Interface>, BindingScopeConfiguratorError> + ) -> Result< + BindingWhenConfigurator<Interface, DIContainerType>, + BindingScopeConfiguratorError, + > { let singleton: SingletonPtr<Implementation> = SingletonPtr::from( Implementation::resolve(&self.di_container, Vec::new()) .map_err(BindingScopeConfiguratorError::SingletonResolveFailed)?, ); - let mut bindings_mut = self.di_container.bindings.borrow_mut(); - - bindings_mut.set::<Interface>(None, Box::new(SingletonProvider::new(singleton))); + self.di_container + .set_binding::<Interface>(None, Box::new(SingletonProvider::new(singleton))); Ok(BindingWhenConfigurator::new(self.di_container.clone())) } diff --git a/src/di_container/blocking/binding/when_configurator.rs b/src/di_container/blocking/binding/when_configurator.rs index 9cd9bb6..5b9a8c0 100644 --- a/src/di_container/blocking/binding/when_configurator.rs +++ b/src/di_container/blocking/binding/when_configurator.rs @@ -1,25 +1,31 @@ -//! When configurator for a binding for types inside of a [`DIContainer`]. +//! When configurator for a binding for types inside of a [`IDIContainer`]. +//! +//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer use std::any::type_name; use std::marker::PhantomData; use std::rc::Rc; -use crate::di_container::blocking::DIContainer; +use crate::di_container::blocking::IDIContainer; use crate::errors::di_container::BindingWhenConfiguratorError; -/// When configurator for a binding for type 'Interface' inside a [`DIContainer`]. -pub struct BindingWhenConfigurator<Interface> +/// When configurator for a binding for type 'Interface' inside a [`IDIContainer`]. +/// +/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer +pub struct BindingWhenConfigurator<Interface, DIContainerType> where Interface: 'static + ?Sized, + DIContainerType: IDIContainer, { - di_container: Rc<DIContainer>, + di_container: Rc<DIContainerType>, interface_phantom: PhantomData<Interface>, } -impl<Interface> BindingWhenConfigurator<Interface> +impl<Interface, DIContainerType> BindingWhenConfigurator<Interface, DIContainerType> where Interface: 'static + ?Sized, + DIContainerType: IDIContainer, { - pub(crate) fn new(di_container: Rc<DIContainer>) -> Self + pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self { Self { di_container, @@ -36,19 +42,21 @@ where name: &'static str, ) -> Result<(), BindingWhenConfiguratorError> { - let mut bindings_mut = self.di_container.bindings.borrow_mut(); + let binding = self + .di_container + .remove_binding::<Interface>(None) + .map_or_else( + || { + Err(BindingWhenConfiguratorError::BindingNotFound(type_name::< + Interface, + >( + ))) + }, + Ok, + )?; - let binding = bindings_mut.remove::<Interface>(None).map_or_else( - || { - Err(BindingWhenConfiguratorError::BindingNotFound(type_name::< - Interface, - >( - ))) - }, - Ok, - )?; - - bindings_mut.set::<Interface>(Some(name), binding); + self.di_container + .set_binding::<Interface>(Some(name), binding); Ok(()) } |