diff options
Diffstat (limited to 'src/di_container')
| -rw-r--r-- | src/di_container/asynchronous/binding/builder.rs | 102 | ||||
| -rw-r--r-- | src/di_container/asynchronous/binding/scope_configurator.rs | 75 | ||||
| -rw-r--r-- | src/di_container/asynchronous/binding/when_configurator.rs | 18 | ||||
| -rw-r--r-- | src/di_container/asynchronous/mod.rs | 182 | ||||
| -rw-r--r-- | src/di_container/blocking/binding/builder.rs | 69 | ||||
| -rw-r--r-- | src/di_container/blocking/binding/scope_configurator.rs | 69 | ||||
| -rw-r--r-- | src/di_container/blocking/binding/when_configurator.rs | 18 | ||||
| -rw-r--r-- | src/di_container/blocking/mod.rs | 146 | 
8 files changed, 341 insertions, 338 deletions
diff --git a/src/di_container/asynchronous/binding/builder.rs b/src/di_container/asynchronous/binding/builder.rs index f334cd7..3d03562 100644 --- a/src/di_container/asynchronous/binding/builder.rs +++ b/src/di_container/asynchronous/binding/builder.rs @@ -5,6 +5,7 @@ use std::any::type_name;  use std::marker::PhantomData;  use std::sync::Arc; +use crate::dependency_history::IDependencyHistory;  use crate::di_container::asynchronous::binding::scope_configurator::AsyncBindingScopeConfigurator;  #[cfg(feature = "factory")]  use crate::di_container::asynchronous::binding::when_configurator::AsyncBindingWhenConfigurator; @@ -20,24 +21,33 @@ pub type BoxFn<Args, Return> = Box<(dyn Fn<Args, Output = Return> + Send + Sync)  /// Binding builder for type `Interface` inside a [`IAsyncDIContainer`].  ///  /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer -pub struct AsyncBindingBuilder<Interface, DIContainerType> +pub struct AsyncBindingBuilder<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized + Send + Sync, -    DIContainerType: IAsyncDIContainer, +    DIContainerType: IAsyncDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + Send + Sync,  {      di_container: Arc<DIContainerType>, +    dependency_history_factory: fn() -> DependencyHistoryType, +      interface_phantom: PhantomData<Interface>,  } -impl<Interface, DIContainerType> AsyncBindingBuilder<Interface, DIContainerType> +impl<Interface, DIContainerType, DependencyHistoryType> +    AsyncBindingBuilder<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized + Send + Sync, -    DIContainerType: IAsyncDIContainer, +    DIContainerType: IAsyncDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + Send + Sync + 'static,  { -    pub(crate) fn new(di_container: Arc<DIContainerType>) -> Self +    pub(crate) fn new( +        di_container: Arc<DIContainerType>, +        dependency_history_factory: fn() -> DependencyHistoryType, +    ) -> Self      {          Self {              di_container, +            dependency_history_factory,              interface_phantom: PhantomData,          }      } @@ -88,11 +98,16 @@ where      pub async fn to<Implementation>(          &self,      ) -> Result< -        AsyncBindingScopeConfigurator<Interface, Implementation, DIContainerType>, +        AsyncBindingScopeConfigurator< +            Interface, +            Implementation, +            DIContainerType, +            DependencyHistoryType, +        >,          AsyncBindingBuilderError,      >      where -        Implementation: AsyncInjectable<DIContainerType>, +        Implementation: AsyncInjectable<DIContainerType, DependencyHistoryType>,      {          if self.di_container.has_binding::<Interface>(None).await {              return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::< @@ -101,8 +116,10 @@ where              )));          } -        let binding_scope_configurator = -            AsyncBindingScopeConfigurator::new(self.di_container.clone()); +        let binding_scope_configurator = AsyncBindingScopeConfigurator::new( +            self.di_container.clone(), +            self.dependency_history_factory, +        );          binding_scope_configurator.in_transient_scope().await; @@ -164,7 +181,7 @@ where          &self,          factory_func: &'static FactoryFunc,      ) -> Result< -        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>,          AsyncBindingBuilderError,      >      where @@ -257,7 +274,7 @@ where          &self,          factory_func: &'static FactoryFunc,      ) -> Result< -        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>,          AsyncBindingBuilderError,      >      where @@ -350,7 +367,7 @@ where          &self,          factory_func: &'static FactoryFunc,      ) -> Result< -        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>,          AsyncBindingBuilderError,      >      where @@ -444,7 +461,7 @@ where          &self,          factory_func: &'static FactoryFunc,      ) -> Result< -        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>,          AsyncBindingBuilderError,      >      where @@ -489,13 +506,14 @@ mod tests      use mockall::predicate::eq;      use super::*; -    use crate::test_utils::mocks::async_di_container::MockAsyncDIContainer; -    use crate::test_utils::subjects_async; +    use crate::test_utils::{mocks, subjects_async};      #[tokio::test]      async fn can_bind_to() -> Result<(), Box<dyn Error>>      { -        let mut di_container_mock = MockAsyncDIContainer::new(); +        let mut di_container_mock = mocks::async_di_container::MockAsyncDIContainer::< +            mocks::MockDependencyHistory, +        >::new();          di_container_mock              .expect_has_binding::<dyn subjects_async::IUserManager>() @@ -511,8 +529,12 @@ mod tests          let binding_builder = AsyncBindingBuilder::<              dyn subjects_async::IUserManager, -            MockAsyncDIContainer, -        >::new(Arc::new(di_container_mock)); +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Arc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          binding_builder.to::<subjects_async::UserManager>().await?; @@ -534,7 +556,8 @@ mod tests              subjects_async::Number,          ) -> dyn subjects_async::IUserManager; -        let mut di_container_mock = MockAsyncDIContainer::new(); +        let mut di_container_mock = +            mocks::async_di_container::MockAsyncDIContainer::new();          di_container_mock              .expect_has_binding::<IUserManagerFactory>() @@ -550,8 +573,12 @@ mod tests          let binding_builder = AsyncBindingBuilder::<              IUserManagerFactory, -            MockAsyncDIContainer, -        >::new(Arc::new(di_container_mock)); +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Arc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          binding_builder              .to_factory(&|_| { @@ -577,7 +604,8 @@ mod tests          #[factory(async = true)]          type IUserManagerFactory = dyn Fn(String) -> dyn subjects_async::IUserManager; -        let mut di_container_mock = MockAsyncDIContainer::new(); +        let mut di_container_mock = +            mocks::async_di_container::MockAsyncDIContainer::new();          di_container_mock              .expect_has_binding::<IUserManagerFactory>() @@ -593,8 +621,12 @@ mod tests          let binding_builder = AsyncBindingBuilder::<              IUserManagerFactory, -            MockAsyncDIContainer, -        >::new(Arc::new(di_container_mock)); +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Arc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          binding_builder              .to_async_factory(&|_| { @@ -621,7 +653,8 @@ mod tests          declare_default_factory!(dyn subjects_async::IUserManager); -        let mut di_container_mock = MockAsyncDIContainer::new(); +        let mut di_container_mock = +            mocks::async_di_container::MockAsyncDIContainer::new();          di_container_mock              .expect_has_binding::<dyn subjects_async::IUserManager>() @@ -637,8 +670,12 @@ mod tests          let binding_builder = AsyncBindingBuilder::<              dyn subjects_async::IUserManager, -            MockAsyncDIContainer, -        >::new(Arc::new(di_container_mock)); +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Arc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          binding_builder              .to_default_factory(&|_| { @@ -665,7 +702,8 @@ mod tests          declare_default_factory!(dyn subjects_async::IUserManager, async = true); -        let mut di_container_mock = MockAsyncDIContainer::new(); +        let mut di_container_mock = +            mocks::async_di_container::MockAsyncDIContainer::new();          di_container_mock              .expect_has_binding::<dyn subjects_async::IUserManager>() @@ -681,8 +719,12 @@ mod tests          let binding_builder = AsyncBindingBuilder::<              dyn subjects_async::IUserManager, -            MockAsyncDIContainer, -        >::new(Arc::new(di_container_mock)); +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Arc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          binding_builder              .to_async_default_factory(&|_| { diff --git a/src/di_container/asynchronous/binding/scope_configurator.rs b/src/di_container/asynchronous/binding/scope_configurator.rs index e2e916a..b5923ec 100644 --- a/src/di_container/asynchronous/binding/scope_configurator.rs +++ b/src/di_container/asynchronous/binding/scope_configurator.rs @@ -4,6 +4,7 @@  use std::marker::PhantomData;  use std::sync::Arc; +use crate::dependency_history::IDependencyHistory;  use crate::di_container::asynchronous::binding::when_configurator::AsyncBindingWhenConfigurator;  use crate::di_container::asynchronous::IAsyncDIContainer;  use crate::errors::async_di_container::AsyncBindingScopeConfiguratorError; @@ -14,28 +15,45 @@ use crate::ptr::ThreadsafeSingletonPtr;  /// Scope configurator for a binding for type 'Interface' inside a [`IAsyncDIContainer`].  ///  /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer -pub struct AsyncBindingScopeConfigurator<Interface, Implementation, DIContainerType> -where +pub struct AsyncBindingScopeConfigurator< +    Interface, +    Implementation, +    DIContainerType, +    DependencyHistoryType, +> where      Interface: 'static + ?Sized + Send + Sync, -    Implementation: AsyncInjectable<DIContainerType>, -    DIContainerType: IAsyncDIContainer, +    Implementation: AsyncInjectable<DIContainerType, DependencyHistoryType>, +    DIContainerType: IAsyncDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + Send + Sync,  {      di_container: Arc<DIContainerType>, +    dependency_history_factory: fn() -> DependencyHistoryType, +      interface_phantom: PhantomData<Interface>,      implementation_phantom: PhantomData<Implementation>,  } -impl<Interface, Implementation, DIContainerType> -    AsyncBindingScopeConfigurator<Interface, Implementation, DIContainerType> +impl<Interface, Implementation, DIContainerType, DependencyHistoryType> +    AsyncBindingScopeConfigurator< +        Interface, +        Implementation, +        DIContainerType, +        DependencyHistoryType, +    >  where      Interface: 'static + ?Sized + Send + Sync, -    Implementation: AsyncInjectable<DIContainerType>, -    DIContainerType: IAsyncDIContainer, +    Implementation: AsyncInjectable<DIContainerType, DependencyHistoryType>, +    DIContainerType: IAsyncDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + Send + Sync + 'static,  { -    pub(crate) fn new(di_container: Arc<DIContainerType>) -> Self +    pub(crate) fn new( +        di_container: Arc<DIContainerType>, +        dependency_history_factory: fn() -> DependencyHistoryType, +    ) -> Self      {          Self {              di_container, +            dependency_history_factory,              interface_phantom: PhantomData,              implementation_phantom: PhantomData,          } @@ -46,14 +64,16 @@ where      /// This is the default.      pub async fn in_transient_scope(          &self, -    ) -> AsyncBindingWhenConfigurator<Interface, DIContainerType> +    ) -> AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>      {          self.di_container              .set_binding::<Interface>(                  None, -                Box::new( -                    AsyncTransientTypeProvider::<Implementation, DIContainerType>::new(), -                ), +                Box::new(AsyncTransientTypeProvider::< +                    Implementation, +                    DIContainerType, +                    DependencyHistoryType, +                >::new()),              )              .await; @@ -67,17 +87,18 @@ where      pub async fn in_singleton_scope(          &self,      ) -> Result< -        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>,          AsyncBindingScopeConfiguratorError,      >      {          let singleton: ThreadsafeSingletonPtr<Implementation> =              ThreadsafeSingletonPtr::from( -                Implementation::resolve(&self.di_container, Vec::new()) -                    .await -                    .map_err( -                        AsyncBindingScopeConfiguratorError::SingletonResolveFailed, -                    )?, +                Implementation::resolve( +                    &self.di_container, +                    (self.dependency_history_factory)(), +                ) +                .await +                .map_err(AsyncBindingScopeConfiguratorError::SingletonResolveFailed)?,              );          self.di_container @@ -112,8 +133,12 @@ mod tests          let binding_scope_configurator = AsyncBindingScopeConfigurator::<              dyn subjects_async::IUserManager,              subjects_async::UserManager, -            mocks::async_di_container::MockAsyncDIContainer, -        >::new(Arc::new(di_container_mock)); +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Arc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          binding_scope_configurator.in_transient_scope().await;      } @@ -133,8 +158,12 @@ mod tests          let binding_scope_configurator = AsyncBindingScopeConfigurator::<              dyn subjects_async::IUserManager,              subjects_async::UserManager, -            mocks::async_di_container::MockAsyncDIContainer, -        >::new(Arc::new(di_container_mock)); +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Arc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          assert!(matches!(              binding_scope_configurator.in_singleton_scope().await, diff --git a/src/di_container/asynchronous/binding/when_configurator.rs b/src/di_container/asynchronous/binding/when_configurator.rs index 9a1505b..4d56347 100644 --- a/src/di_container/asynchronous/binding/when_configurator.rs +++ b/src/di_container/asynchronous/binding/when_configurator.rs @@ -5,31 +5,38 @@ use std::any::type_name;  use std::marker::PhantomData;  use std::sync::Arc; +use crate::dependency_history::IDependencyHistory;  use crate::di_container::asynchronous::IAsyncDIContainer;  use crate::errors::async_di_container::AsyncBindingWhenConfiguratorError;  /// When configurator for a binding for type 'Interface' inside a [`IAsyncDIContainer`].  ///  /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer -pub struct AsyncBindingWhenConfigurator<Interface, DIContainerType> +pub struct AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized + Send + Sync, -    DIContainerType: IAsyncDIContainer, +    DIContainerType: IAsyncDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + Send + Sync,  {      di_container: Arc<DIContainerType>, +      interface_phantom: PhantomData<Interface>, +    dependency_history_phantom: PhantomData<DependencyHistoryType>,  } -impl<Interface, DIContainerType> AsyncBindingWhenConfigurator<Interface, DIContainerType> +impl<Interface, DIContainerType, DependencyHistoryType> +    AsyncBindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized + Send + Sync, -    DIContainerType: IAsyncDIContainer, +    DIContainerType: IAsyncDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + Send + Sync,  {      pub(crate) fn new(di_container: Arc<DIContainerType>) -> Self      {          Self {              di_container,              interface_phantom: PhantomData, +            dependency_history_phantom: PhantomData,          }      } @@ -92,7 +99,8 @@ mod tests          let binding_when_configurator = AsyncBindingWhenConfigurator::<              dyn subjects_async::INumber, -            mocks::async_di_container::MockAsyncDIContainer, +            mocks::async_di_container::MockAsyncDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory,          >::new(Arc::new(di_container_mock));          assert!(matches!( diff --git a/src/di_container/asynchronous/mod.rs b/src/di_container/asynchronous/mod.rs index 128fbbe..99a33be 100644 --- a/src/di_container/asynchronous/mod.rs +++ b/src/di_container/asynchronous/mod.rs @@ -57,6 +57,7 @@ use std::sync::Arc;  use async_trait::async_trait;  use tokio::sync::Mutex; +use crate::dependency_history::{DependencyHistory, IDependencyHistory};  use crate::di_container::asynchronous::binding::builder::AsyncBindingBuilder;  use crate::di_container::binding_storage::DIContainerBindingStorage;  use crate::errors::async_di_container::AsyncDIContainerError; @@ -71,12 +72,16 @@ pub mod prelude;  /// Dependency injection container interface.  #[async_trait] -pub trait IAsyncDIContainer: -    Sized + 'static + Send + Sync + details::DIContainerInternals +pub trait IAsyncDIContainer<DependencyHistoryType>: +    Sized + 'static + Send + Sync + details::DIContainerInternals<DependencyHistoryType> +where +    DependencyHistoryType: IDependencyHistory + Send + Sync,  {      /// Returns a new [`AsyncBindingBuilder`] for the given interface.      #[must_use] -    fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface, Self> +    fn bind<Interface>( +        self: &mut Arc<Self>, +    ) -> AsyncBindingBuilder<Interface, Self, DependencyHistoryType>      where          Interface: 'static + ?Sized + Send + Sync; @@ -114,7 +119,7 @@ pub trait IAsyncDIContainer:      #[doc(hidden)]      async fn get_bound<Interface>(          self: &Arc<Self>, -        dependency_history: Vec<&'static str>, +        dependency_history: DependencyHistoryType,          name: Option<&'static str>,      ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>      where @@ -124,7 +129,8 @@ pub trait IAsyncDIContainer:  /// Dependency injection container.  pub struct AsyncDIContainer  { -    binding_storage: Mutex<DIContainerBindingStorage<dyn IAsyncProvider<Self>>>, +    binding_storage: +        Mutex<DIContainerBindingStorage<dyn IAsyncProvider<Self, DependencyHistory>>>,  }  impl AsyncDIContainer @@ -140,14 +146,16 @@ impl AsyncDIContainer  }  #[async_trait] -impl IAsyncDIContainer for AsyncDIContainer +impl IAsyncDIContainer<DependencyHistory> for AsyncDIContainer  {      #[must_use] -    fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface, Self> +    fn bind<Interface>( +        self: &mut Arc<Self>, +    ) -> AsyncBindingBuilder<Interface, Self, DependencyHistory>      where          Interface: 'static + ?Sized + Send + Sync,      { -        AsyncBindingBuilder::new(self.clone()) +        AsyncBindingBuilder::new(self.clone(), DependencyHistory::new)      }      fn get<'a, 'b, Interface>( @@ -158,7 +166,10 @@ impl IAsyncDIContainer for AsyncDIContainer          'a: 'b,          Self: 'b,      { -        Box::pin(async { self.get_bound::<Interface>(Vec::new(), None).await }) +        Box::pin(async { +            self.get_bound::<Interface>(DependencyHistory::new(), None) +                .await +        })      }      fn get_named<'a, 'b, Interface>( @@ -170,12 +181,15 @@ impl IAsyncDIContainer for AsyncDIContainer          'a: 'b,          Self: 'b,      { -        Box::pin(async { self.get_bound::<Interface>(Vec::new(), Some(name)).await }) +        Box::pin(async { +            self.get_bound::<Interface>(DependencyHistory::new(), Some(name)) +                .await +        })      }      async fn get_bound<Interface>(          self: &Arc<Self>, -        dependency_history: Vec<&'static str>, +        dependency_history: DependencyHistory,          name: Option<&'static str>,      ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>      where @@ -190,7 +204,7 @@ impl IAsyncDIContainer for AsyncDIContainer  }  #[async_trait] -impl details::DIContainerInternals for AsyncDIContainer +impl details::DIContainerInternals<DependencyHistory> for AsyncDIContainer  {      async fn has_binding<Interface>(self: &Arc<Self>, name: Option<&'static str>) -> bool      where @@ -202,7 +216,7 @@ impl details::DIContainerInternals for AsyncDIContainer      async fn set_binding<Interface>(          self: &Arc<Self>,          name: Option<&'static str>, -        provider: Box<dyn IAsyncProvider<Self>>, +        provider: Box<dyn IAsyncProvider<Self, DependencyHistory>>,      ) where          Interface: 'static + ?Sized,      { @@ -215,7 +229,7 @@ impl details::DIContainerInternals for AsyncDIContainer      async fn remove_binding<Interface>(          self: &Arc<Self>,          name: Option<&'static str>, -    ) -> Option<Box<dyn IAsyncProvider<Self>>> +    ) -> Option<Box<dyn IAsyncProvider<Self, DependencyHistory>>>      where          Interface: 'static + ?Sized,      { @@ -227,7 +241,7 @@ impl AsyncDIContainer  {      async fn handle_binding_providable<Interface>(          self: &Arc<Self>, -        binding_providable: AsyncProvidable<Self>, +        binding_providable: AsyncProvidable<Self, DependencyHistory>,      ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>      where          Interface: 'static + ?Sized + Send + Sync, @@ -344,8 +358,8 @@ impl AsyncDIContainer      async fn get_binding_providable<Interface>(          self: &Arc<Self>,          name: Option<&'static str>, -        dependency_history: Vec<&'static str>, -    ) -> Result<AsyncProvidable<Self>, AsyncDIContainerError> +        dependency_history: DependencyHistory, +    ) -> Result<AsyncProvidable<Self, DependencyHistory>, AsyncDIContainerError>      where          Interface: 'static + ?Sized + Send + Sync,      { @@ -384,10 +398,13 @@ pub(crate) mod details      use async_trait::async_trait; +    use crate::dependency_history::IDependencyHistory;      use crate::provider::r#async::IAsyncProvider;      #[async_trait] -    pub trait DIContainerInternals +    pub trait DIContainerInternals<DependencyHistoryType> +    where +        DependencyHistoryType: IDependencyHistory,      {          async fn has_binding<Interface>(              self: &Arc<Self>, @@ -399,14 +416,14 @@ pub(crate) mod details          async fn set_binding<Interface>(              self: &Arc<Self>,              name: Option<&'static str>, -            provider: Box<dyn IAsyncProvider<Self>>, +            provider: Box<dyn IAsyncProvider<Self, DependencyHistoryType>>,          ) where              Interface: 'static + ?Sized;          async fn remove_binding<Interface>(              self: &Arc<Self>,              name: Option<&'static str>, -        ) -> Option<Box<dyn IAsyncProvider<Self>>> +        ) -> Option<Box<dyn IAsyncProvider<Self, DependencyHistoryType>>>          where              Interface: 'static + ?Sized;      } @@ -417,39 +434,20 @@ mod tests  {      use std::error::Error; -    use async_trait::async_trait; -    use mockall::mock; -      use super::*; -    use crate::errors::injectable::InjectableError;      use crate::ptr::{ThreadsafeSingletonPtr, TransientPtr}; +    use crate::test_utils::mocks::async_provider::MockAsyncProvider;      use crate::test_utils::subjects_async;      #[tokio::test]      async fn can_get() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            #[async_trait] -            impl IAsyncProvider<AsyncDIContainer> for Provider -            { -                async fn provide( -                    &self, -                    di_container: &Arc<AsyncDIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; - -                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>; -            } -        } -          let di_container = AsyncDIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = MockAsyncProvider::new();          mock_provider.expect_do_clone().returning(|| { -            let mut inner_mock_provider = MockProvider::new(); +            let mut inner_mock_provider = MockAsyncProvider::new();              inner_mock_provider.expect_provide().returning(|_, _| {                  Ok(AsyncProvidable::Transient(TransientPtr::new( @@ -479,28 +477,12 @@ mod tests      #[tokio::test]      async fn can_get_named() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            #[async_trait] -            impl IAsyncProvider<AsyncDIContainer> for Provider -            { -                async fn provide( -                    &self, -                    di_container: &Arc<AsyncDIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; - -                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>; -            } -        } -          let di_container = AsyncDIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = MockAsyncProvider::new();          mock_provider.expect_do_clone().returning(|| { -            let mut inner_mock_provider = MockProvider::new(); +            let mut inner_mock_provider = MockAsyncProvider::new();              inner_mock_provider.expect_provide().returning(|_, _| {                  Ok(AsyncProvidable::Transient(TransientPtr::new( @@ -533,32 +515,16 @@ mod tests      #[tokio::test]      async fn can_get_singleton() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            #[async_trait] -            impl IAsyncProvider<AsyncDIContainer> for Provider -            { -                async fn provide( -                    &self, -                    di_container: &Arc<AsyncDIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; - -                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>; -            } -        } -          let di_container = AsyncDIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = MockAsyncProvider::new();          let mut singleton = ThreadsafeSingletonPtr::new(subjects_async::Number::new());          ThreadsafeSingletonPtr::get_mut(&mut singleton).unwrap().num = 2820;          mock_provider.expect_do_clone().returning(move || { -            let mut inner_mock_provider = MockProvider::new(); +            let mut inner_mock_provider = MockAsyncProvider::new();              let singleton_clone = singleton.clone(); @@ -597,32 +563,16 @@ mod tests      #[tokio::test]      async fn can_get_singleton_named() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            #[async_trait] -            impl IAsyncProvider<AsyncDIContainer> for Provider -            { -                async fn provide( -                    &self, -                    di_container: &Arc<AsyncDIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; - -                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>; -            } -        } -          let di_container = AsyncDIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = MockAsyncProvider::new();          let mut singleton = ThreadsafeSingletonPtr::new(subjects_async::Number::new());          ThreadsafeSingletonPtr::get_mut(&mut singleton).unwrap().num = 2820;          mock_provider.expect_do_clone().returning(move || { -            let mut inner_mock_provider = MockProvider::new(); +            let mut inner_mock_provider = MockAsyncProvider::new();              let singleton_clone = singleton.clone(); @@ -707,32 +657,16 @@ mod tests          #[crate::factory(threadsafe = true)]          type IUserManagerFactory = dyn Fn(Vec<i128>) -> dyn IUserManager; -        mock! { -            Provider {} - -            #[async_trait] -            impl IAsyncProvider<AsyncDIContainer> for Provider -            { -                async fn provide( -                    &self, -                    di_container: &Arc<AsyncDIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; - -                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>; -            } -        } -          let di_container = AsyncDIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = MockAsyncProvider::new();          mock_provider.expect_do_clone().returning(|| {              type FactoryFunc = Box<                  (dyn Fn<(Vec<i128>,), Output = TransientPtr<dyn IUserManager>> + Send + Sync)              >; -            let mut inner_mock_provider = MockProvider::new(); +            let mut inner_mock_provider = MockAsyncProvider::new();              let factory_func: &'static (dyn Fn<                  (Arc<AsyncDIContainer>,), @@ -818,32 +752,16 @@ mod tests          #[crate::factory(threadsafe = true)]          type IUserManagerFactory = dyn Fn(Vec<i128>) -> dyn IUserManager; -        mock! { -            Provider {} - -            #[async_trait] -            impl IAsyncProvider<AsyncDIContainer> for Provider -            { -                async fn provide( -                    &self, -                    di_container: &Arc<AsyncDIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; - -                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>; -            } -        } -          let di_container = AsyncDIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = MockAsyncProvider::new();          mock_provider.expect_do_clone().returning(|| {              type FactoryFunc = Box<                  (dyn Fn<(Vec<i128>,), Output = TransientPtr<dyn IUserManager>> + Send + Sync)              >; -            let mut inner_mock_provider = MockProvider::new(); +            let mut inner_mock_provider = MockAsyncProvider::new();              let factory_func: &'static (dyn Fn<                  (Arc<AsyncDIContainer>,), diff --git a/src/di_container/blocking/binding/builder.rs b/src/di_container/blocking/binding/builder.rs index e1c1561..7aa1755 100644 --- a/src/di_container/blocking/binding/builder.rs +++ b/src/di_container/blocking/binding/builder.rs @@ -5,6 +5,7 @@ use std::any::type_name;  use std::marker::PhantomData;  use std::rc::Rc; +use crate::dependency_history::IDependencyHistory;  use crate::di_container::blocking::binding::scope_configurator::BindingScopeConfigurator;  #[cfg(feature = "factory")]  use crate::di_container::blocking::binding::when_configurator::BindingWhenConfigurator; @@ -15,24 +16,33 @@ use crate::interfaces::injectable::Injectable;  /// Binding builder for type `Interface` inside a [`IDIContainer`].  ///  /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer -pub struct BindingBuilder<Interface, DIContainerType> +pub struct BindingBuilder<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized, -    DIContainerType: IDIContainer, +    DIContainerType: IDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory,  {      di_container: Rc<DIContainerType>, +    dependency_history_factory: fn() -> DependencyHistoryType, +      interface_phantom: PhantomData<Interface>,  } -impl<Interface, DIContainerType> BindingBuilder<Interface, DIContainerType> +impl<Interface, DIContainerType, DependencyHistoryType> +    BindingBuilder<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized, -    DIContainerType: IDIContainer, +    DIContainerType: IDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + 'static,  { -    pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self +    pub(crate) fn new( +        di_container: Rc<DIContainerType>, +        dependency_history_factory: fn() -> DependencyHistoryType, +    ) -> Self      {          Self {              di_container, +            dependency_history_factory,              interface_phantom: PhantomData,          }      } @@ -82,11 +92,16 @@ where      pub fn to<Implementation>(          &self,      ) -> Result< -        BindingScopeConfigurator<Interface, Implementation, DIContainerType>, +        BindingScopeConfigurator< +            Interface, +            Implementation, +            DIContainerType, +            DependencyHistoryType, +        >,          BindingBuilderError,      >      where -        Implementation: Injectable<DIContainerType>, +        Implementation: Injectable<DIContainerType, DependencyHistoryType>,      {          {              if self.di_container.has_binding::<Interface>(None) { @@ -97,8 +112,10 @@ where              }          } -        let binding_scope_configurator = -            BindingScopeConfigurator::new(self.di_container.clone()); +        let binding_scope_configurator = BindingScopeConfigurator::new( +            self.di_container.clone(), +            self.dependency_history_factory, +        );          binding_scope_configurator.in_transient_scope(); @@ -176,7 +193,10 @@ where      pub fn to_factory<Args, Return, Func>(          &self,          factory_func: &'static Func, -    ) -> Result<BindingWhenConfigurator<Interface, DIContainerType>, BindingBuilderError> +    ) -> Result< +        BindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>, +        BindingBuilderError, +    >      where          Args: 'static,          Return: 'static + ?Sized, @@ -262,7 +282,10 @@ where      pub fn to_default_factory<Return, FactoryFunc>(          &self,          factory_func: &'static FactoryFunc, -    ) -> Result<BindingWhenConfigurator<Interface, DIContainerType>, BindingBuilderError> +    ) -> Result< +        BindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>, +        BindingBuilderError, +    >      where          Return: 'static + ?Sized,          FactoryFunc: Fn< @@ -323,8 +346,12 @@ mod tests          let binding_builder = BindingBuilder::<              dyn subjects::INumber, -            mocks::blocking_di_container::MockDIContainer, -        >::new(Rc::new(mock_di_container)); +            mocks::blocking_di_container::MockDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Rc::new(mock_di_container), +            mocks::MockDependencyHistory::new, +        );          binding_builder.to::<subjects::Number>()?; @@ -358,8 +385,12 @@ mod tests          let binding_builder = BindingBuilder::<              IUserManagerFactory, -            mocks::blocking_di_container::MockDIContainer, -        >::new(Rc::new(mock_di_container)); +            mocks::blocking_di_container::MockDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Rc::new(mock_di_container), +            mocks::MockDependencyHistory::new, +        );          binding_builder.to_factory(&|_| {              Box::new(move |_num, _text| { @@ -400,8 +431,12 @@ mod tests          let binding_builder = BindingBuilder::<              dyn subjects::IUserManager, -            mocks::blocking_di_container::MockDIContainer, -        >::new(Rc::new(mock_di_container)); +            mocks::blocking_di_container::MockDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Rc::new(mock_di_container), +            mocks::MockDependencyHistory::new, +        );          binding_builder.to_default_factory(&|_| {              Box::new(move || { diff --git a/src/di_container/blocking/binding/scope_configurator.rs b/src/di_container/blocking/binding/scope_configurator.rs index dc33cbc..6c6c32d 100644 --- a/src/di_container/blocking/binding/scope_configurator.rs +++ b/src/di_container/blocking/binding/scope_configurator.rs @@ -4,6 +4,7 @@  use std::marker::PhantomData;  use std::rc::Rc; +use crate::dependency_history::IDependencyHistory;  use crate::di_container::blocking::binding::when_configurator::BindingWhenConfigurator;  use crate::di_container::blocking::IDIContainer;  use crate::errors::di_container::BindingScopeConfiguratorError; @@ -14,28 +15,45 @@ use crate::ptr::SingletonPtr;  /// Scope configurator for a binding for type 'Interface' inside a [`IDIContainer`].  ///  /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer -pub struct BindingScopeConfigurator<Interface, Implementation, DIContainerType> -where +pub struct BindingScopeConfigurator< +    Interface, +    Implementation, +    DIContainerType, +    DependencyHistoryType, +> where      Interface: 'static + ?Sized, -    Implementation: Injectable<DIContainerType>, -    DIContainerType: IDIContainer, +    Implementation: Injectable<DIContainerType, DependencyHistoryType>, +    DIContainerType: IDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory,  {      di_container: Rc<DIContainerType>, +    dependency_history_factory: fn() -> DependencyHistoryType, +      interface_phantom: PhantomData<Interface>,      implementation_phantom: PhantomData<Implementation>,  } -impl<Interface, Implementation, DIContainerType> -    BindingScopeConfigurator<Interface, Implementation, DIContainerType> +impl<Interface, Implementation, DIContainerType, DependencyHistoryType> +    BindingScopeConfigurator< +        Interface, +        Implementation, +        DIContainerType, +        DependencyHistoryType, +    >  where      Interface: 'static + ?Sized, -    Implementation: Injectable<DIContainerType>, -    DIContainerType: IDIContainer, +    Implementation: Injectable<DIContainerType, DependencyHistoryType>, +    DIContainerType: IDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory + 'static,  { -    pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self +    pub(crate) fn new( +        di_container: Rc<DIContainerType>, +        dependency_history_factory: fn() -> DependencyHistoryType, +    ) -> Self      {          Self {              di_container, +            dependency_history_factory,              interface_phantom: PhantomData,              implementation_phantom: PhantomData,          } @@ -47,11 +65,15 @@ where      #[allow(clippy::must_use_candidate)]      pub fn in_transient_scope(          &self, -    ) -> BindingWhenConfigurator<Interface, DIContainerType> +    ) -> BindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>      {          self.di_container.set_binding::<Interface>(              None, -            Box::new(TransientTypeProvider::<Implementation, DIContainerType>::new()), +            Box::new(TransientTypeProvider::< +                Implementation, +                DIContainerType, +                DependencyHistoryType, +            >::new()),          );          BindingWhenConfigurator::new(self.di_container.clone()) @@ -64,13 +86,16 @@ where      pub fn in_singleton_scope(          &self,      ) -> Result< -        BindingWhenConfigurator<Interface, DIContainerType>, +        BindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>,          BindingScopeConfiguratorError,      >      {          let singleton: SingletonPtr<Implementation> = SingletonPtr::from( -            Implementation::resolve(&self.di_container, Vec::new()) -                .map_err(BindingScopeConfiguratorError::SingletonResolveFailed)?, +            Implementation::resolve( +                &self.di_container, +                (self.dependency_history_factory)(), +            ) +            .map_err(BindingScopeConfiguratorError::SingletonResolveFailed)?,          );          self.di_container @@ -100,8 +125,12 @@ mod tests          let binding_scope_configurator = BindingScopeConfigurator::<              dyn subjects::IUserManager,              subjects::UserManager, -            mocks::blocking_di_container::MockDIContainer, -        >::new(Rc::new(di_container_mock)); +            mocks::blocking_di_container::MockDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Rc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          binding_scope_configurator.in_transient_scope();      } @@ -120,8 +149,12 @@ mod tests          let binding_scope_configurator = BindingScopeConfigurator::<              dyn subjects::IUserManager,              subjects::UserManager, -            mocks::blocking_di_container::MockDIContainer, -        >::new(Rc::new(di_container_mock)); +            mocks::blocking_di_container::MockDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory, +        >::new( +            Rc::new(di_container_mock), +            mocks::MockDependencyHistory::new, +        );          assert!(matches!(              binding_scope_configurator.in_singleton_scope(), diff --git a/src/di_container/blocking/binding/when_configurator.rs b/src/di_container/blocking/binding/when_configurator.rs index 49c9d9e..f93806b 100644 --- a/src/di_container/blocking/binding/when_configurator.rs +++ b/src/di_container/blocking/binding/when_configurator.rs @@ -5,31 +5,38 @@ use std::any::type_name;  use std::marker::PhantomData;  use std::rc::Rc; +use crate::dependency_history::IDependencyHistory;  use crate::di_container::blocking::IDIContainer;  use crate::errors::di_container::BindingWhenConfiguratorError;  /// When configurator for a binding for type 'Interface' inside a [`IDIContainer`].  ///  /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer -pub struct BindingWhenConfigurator<Interface, DIContainerType> +pub struct BindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized, -    DIContainerType: IDIContainer, +    DIContainerType: IDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory,  {      di_container: Rc<DIContainerType>, +      interface_phantom: PhantomData<Interface>, +    dependency_history_phantom: PhantomData<DependencyHistoryType>,  } -impl<Interface, DIContainerType> BindingWhenConfigurator<Interface, DIContainerType> +impl<Interface, DIContainerType, DependencyHistoryType> +    BindingWhenConfigurator<Interface, DIContainerType, DependencyHistoryType>  where      Interface: 'static + ?Sized, -    DIContainerType: IDIContainer, +    DIContainerType: IDIContainer<DependencyHistoryType>, +    DependencyHistoryType: IDependencyHistory,  {      pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self      {          Self {              di_container,              interface_phantom: PhantomData, +            dependency_history_phantom: PhantomData,          }      } @@ -90,7 +97,8 @@ mod tests          let binding_when_configurator = BindingWhenConfigurator::<              dyn subjects::INumber, -            mocks::blocking_di_container::MockDIContainer, +            mocks::blocking_di_container::MockDIContainer<mocks::MockDependencyHistory>, +            mocks::MockDependencyHistory,          >::new(Rc::new(di_container_mock));          assert!(matches!( diff --git a/src/di_container/blocking/mod.rs b/src/di_container/blocking/mod.rs index bf77aba..6338118 100644 --- a/src/di_container/blocking/mod.rs +++ b/src/di_container/blocking/mod.rs @@ -54,6 +54,7 @@ use std::any::type_name;  use std::cell::RefCell;  use std::rc::Rc; +use crate::dependency_history::{DependencyHistory, IDependencyHistory};  use crate::di_container::binding_storage::DIContainerBindingStorage;  use crate::di_container::blocking::binding::builder::BindingBuilder;  use crate::errors::di_container::DIContainerError; @@ -65,10 +66,15 @@ pub mod binding;  pub mod prelude;  /// Blocking dependency injection container interface. -pub trait IDIContainer: Sized + 'static + details::DIContainerInternals +pub trait IDIContainer<DependencyHistoryType>: +    Sized + 'static + details::DIContainerInternals<DependencyHistoryType> +where +    DependencyHistoryType: IDependencyHistory,  {      /// Returns a new [`BindingBuilder`] for the given interface. -    fn bind<Interface>(self: &mut Rc<Self>) -> BindingBuilder<Interface, Self> +    fn bind<Interface>( +        self: &mut Rc<Self>, +    ) -> BindingBuilder<Interface, Self, DependencyHistoryType>      where          Interface: 'static + ?Sized; @@ -100,7 +106,7 @@ pub trait IDIContainer: Sized + 'static + details::DIContainerInternals      #[doc(hidden)]      fn get_bound<Interface>(          self: &Rc<Self>, -        dependency_history: Vec<&'static str>, +        dependency_history: DependencyHistoryType,          name: Option<&'static str>,      ) -> Result<SomePtr<Interface>, DIContainerError>      where @@ -110,7 +116,8 @@ pub trait IDIContainer: Sized + 'static + details::DIContainerInternals  /// Blocking dependency injection container.  pub struct DIContainer  { -    binding_storage: RefCell<DIContainerBindingStorage<dyn IProvider<Self>>>, +    binding_storage: +        RefCell<DIContainerBindingStorage<dyn IProvider<Self, DependencyHistory>>>,  }  impl DIContainer @@ -125,21 +132,23 @@ impl DIContainer      }  } -impl IDIContainer for DIContainer +impl IDIContainer<DependencyHistory> for DIContainer  {      #[must_use] -    fn bind<Interface>(self: &mut Rc<Self>) -> BindingBuilder<Interface, Self> +    fn bind<Interface>( +        self: &mut Rc<Self>, +    ) -> BindingBuilder<Interface, Self, DependencyHistory>      where          Interface: 'static + ?Sized,      { -        BindingBuilder::<Interface, Self>::new(self.clone()) +        BindingBuilder::new(self.clone(), DependencyHistory::new)      }      fn get<Interface>(self: &Rc<Self>) -> Result<SomePtr<Interface>, DIContainerError>      where          Interface: 'static + ?Sized,      { -        self.get_bound::<Interface>(Vec::new(), None) +        self.get_bound::<Interface>(DependencyHistory::new(), None)      }      fn get_named<Interface>( @@ -149,13 +158,13 @@ impl IDIContainer for DIContainer      where          Interface: 'static + ?Sized,      { -        self.get_bound::<Interface>(Vec::new(), Some(name)) +        self.get_bound::<Interface>(DependencyHistory::new(), Some(name))      }      #[doc(hidden)]      fn get_bound<Interface>(          self: &Rc<Self>, -        dependency_history: Vec<&'static str>, +        dependency_history: DependencyHistory,          name: Option<&'static str>,      ) -> Result<SomePtr<Interface>, DIContainerError>      where @@ -168,7 +177,7 @@ impl IDIContainer for DIContainer      }  } -impl details::DIContainerInternals for DIContainer +impl details::DIContainerInternals<DependencyHistory> for DIContainer  {      fn has_binding<Interface>(self: &Rc<Self>, name: Option<&'static str>) -> bool      where @@ -180,7 +189,7 @@ impl details::DIContainerInternals for DIContainer      fn set_binding<Interface>(          self: &Rc<Self>,          name: Option<&'static str>, -        provider: Box<dyn IProvider<Self>>, +        provider: Box<dyn IProvider<Self, DependencyHistory>>,      ) where          Interface: 'static + ?Sized,      { @@ -192,7 +201,7 @@ impl details::DIContainerInternals for DIContainer      fn remove_binding<Interface>(          self: &Rc<Self>,          name: Option<&'static str>, -    ) -> Option<Box<dyn IProvider<Self>>> +    ) -> Option<Box<dyn IProvider<Self, DependencyHistory>>>      where          Interface: 'static + ?Sized,      { @@ -204,7 +213,7 @@ impl DIContainer  {      fn handle_binding_providable<Interface>(          self: &Rc<Self>, -        binding_providable: Providable<Self>, +        binding_providable: Providable<Self, DependencyHistory>,      ) -> Result<SomePtr<Interface>, DIContainerError>      where          Interface: 'static + ?Sized, @@ -262,8 +271,8 @@ impl DIContainer      fn get_binding_providable<Interface>(          self: &Rc<Self>,          name: Option<&'static str>, -        dependency_history: Vec<&'static str>, -    ) -> Result<Providable<Self>, DIContainerError> +        dependency_history: DependencyHistory, +    ) -> Result<Providable<Self, DependencyHistory>, DIContainerError>      where          Interface: 'static + ?Sized,      { @@ -291,9 +300,12 @@ pub(crate) mod details  {      use std::rc::Rc; +    use crate::dependency_history::IDependencyHistory;      use crate::provider::blocking::IProvider; -    pub trait DIContainerInternals +    pub trait DIContainerInternals<DependencyHistoryType> +    where +        DependencyHistoryType: IDependencyHistory,      {          fn has_binding<Interface>(self: &Rc<Self>, name: Option<&'static str>) -> bool          where @@ -302,14 +314,14 @@ pub(crate) mod details          fn set_binding<Interface>(              self: &Rc<Self>,              name: Option<&'static str>, -            provider: Box<dyn IProvider<Self>>, +            provider: Box<dyn IProvider<Self, DependencyHistoryType>>,          ) where              Interface: 'static + ?Sized;          fn remove_binding<Interface>(              self: &Rc<Self>,              name: Option<&'static str>, -        ) -> Option<Box<dyn IProvider<Self>>> +        ) -> Option<Box<dyn IProvider<Self, DependencyHistoryType>>>          where              Interface: 'static + ?Sized;      } @@ -320,33 +332,16 @@ mod tests  {      use std::error::Error; -    use mockall::mock; -      use super::*; -    use crate::errors::injectable::InjectableError; -    use crate::provider::blocking::IProvider;      use crate::ptr::{SingletonPtr, TransientPtr}; -    use crate::test_utils::subjects; +    use crate::test_utils::{mocks, subjects};      #[test]      fn can_get() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            impl IProvider<DIContainer> for Provider -            { -                fn provide( -                    &self, -                    di_container: &Rc<DIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<Providable<DIContainer>, InjectableError>; -            } -        } -          let di_container = DIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = mocks::blocking_provider::MockProvider::new();          mock_provider.expect_provide().returning(|_, _| {              Ok(Providable::Transient(TransientPtr::new( @@ -369,22 +364,9 @@ mod tests      #[test]      fn can_get_named() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            impl IProvider<DIContainer> for Provider -            { -                fn provide( -                    &self, -                    di_container: &Rc<DIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<Providable<DIContainer>, InjectableError>; -            } -        } -          let di_container = DIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = mocks::blocking_provider::MockProvider::new();          mock_provider.expect_provide().returning(|_, _| {              Ok(Providable::Transient(TransientPtr::new( @@ -407,22 +389,9 @@ mod tests      #[test]      fn can_get_singleton() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            impl IProvider<DIContainer> for Provider -            { -                fn provide( -                    &self, -                    di_container: &Rc<DIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<Providable<DIContainer>, InjectableError>; -            } -        } -          let di_container = DIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = mocks::blocking_provider::MockProvider::new();          let mut singleton = SingletonPtr::new(subjects::Number::new()); @@ -452,22 +421,9 @@ mod tests      #[test]      fn can_get_singleton_named() -> Result<(), Box<dyn Error>>      { -        mock! { -            Provider {} - -            impl IProvider<DIContainer> for Provider -            { -                fn provide( -                    &self, -                    di_container: &Rc<DIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<Providable<DIContainer>, InjectableError>; -            } -        } -          let di_container = DIContainer::new(); -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = mocks::blocking_provider::MockProvider::new();          let mut singleton = SingletonPtr::new(subjects::Number::new()); @@ -552,19 +508,6 @@ mod tests          #[crate::factory]          type IUserManagerFactory = dyn Fn(Vec<i128>) -> dyn IUserManager; -        mock! { -            Provider {} - -            impl IProvider<DIContainer> for Provider -            { -                fn provide( -                    &self, -                    di_container: &Rc<DIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<Providable<DIContainer>, InjectableError>; -            } -        } -          let di_container = DIContainer::new();          let factory_func: &'static FactoryFunc = &|_: Rc<DIContainer>| { @@ -576,7 +519,7 @@ mod tests              })          }; -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = mocks::blocking_provider::MockProvider::new();          mock_provider.expect_provide().returning_st(|_, _| {              Ok(Providable::Factory(FactoryPtr::new(CastableFactory::new( @@ -649,19 +592,6 @@ mod tests          #[crate::factory]          type IUserManagerFactory = dyn Fn(Vec<i128>) -> dyn IUserManager; -        mock! { -            Provider {} - -            impl IProvider<DIContainer> for Provider -            { -                fn provide( -                    &self, -                    di_container: &Rc<DIContainer>, -                    dependency_history: Vec<&'static str>, -                ) -> Result<Providable<DIContainer>, InjectableError>; -            } -        } -          let di_container = DIContainer::new();          let factory_func: &'static FactoryFunc = &|_: Rc<DIContainer>| { @@ -673,7 +603,7 @@ mod tests              })          }; -        let mut mock_provider = MockProvider::new(); +        let mut mock_provider = mocks::blocking_provider::MockProvider::new();          mock_provider.expect_provide().returning_st(|_, _| {              Ok(Providable::Factory(FactoryPtr::new(CastableFactory::new(  | 
