diff options
author | HampusM <hampus@hampusmat.com> | 2022-08-03 14:13:55 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-08-21 18:17:17 +0200 |
commit | b54dee1fb52f259de8b485d050d75c6956750b7f (patch) | |
tree | c2aa02de55da6c2d4c338982afee18ce42465160 /src/di_container.rs | |
parent | c33cf02c9a6fffc6149fd7b59c63ad0d15d61432 (diff) |
feat!: prevent binding the same interface more than once
BREAKING CHANGE: The 'to' and 'to_factory' methods of BindingBuilder now return 'Result'
Diffstat (limited to 'src/di_container.rs')
-rw-r--r-- | src/di_container.rs | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/src/di_container.rs b/src/di_container.rs index e15d921..c33d339 100644 --- a/src/di_container.rs +++ b/src/di_container.rs @@ -92,20 +92,33 @@ where /// Creates a binding of type `Interface` to type `Implementation` inside of the /// associated [`DIContainer`]. - pub fn to<Implementation>(&mut self) + /// + /// # Errors + /// Will return Err if the associated [`DIContainer`] already have a binding for + /// the interface. + pub fn to<Implementation>(&mut self) -> error_stack::Result<(), BindingBuilderError> where Implementation: Injectable, { self.di_container .bindings - .set::<Interface>(Box::new(TransientTypeProvider::<Implementation>::new())); + .set::<Interface>(Box::new(TransientTypeProvider::<Implementation>::new())) + .ok_or_else(|| { + report!(BindingBuilderError).attach_printable(format!( + "Binding already exists for interface '{}'", + type_name::<Interface>() + )) + })?; + + Ok(()) } /// Creates a binding of type `Interface` to a new singleton of type `Implementation` /// inside of the associated [`DIContainer`]. /// /// # Errors - /// Will return Err if creating the singleton fails. + /// Will return Err if creating the singleton fails or if the + /// associated [`DIContainer`] already have a binding for the interface. pub fn to_singleton<Implementation>( &mut self, ) -> error_stack::Result<(), BindingBuilderError> @@ -119,7 +132,13 @@ where self.di_container .bindings - .set::<Interface>(Box::new(SingletonProvider::new(singleton))); + .set::<Interface>(Box::new(SingletonProvider::new(singleton))) + .ok_or_else(|| { + report!(BindingBuilderError).attach_printable(format!( + "Binding already exists for interface '{}'", + type_name::<Interface>() + )) + })?; Ok(()) } @@ -128,22 +147,35 @@ where /// associated [`DIContainer`]. /// /// *This function is only available if Syrette is built with the "factory" feature.* + /// + /// # Errors + /// Will return Err if the associated [`DIContainer`] already have a binding for + /// the interface. #[cfg(feature = "factory")] pub fn to_factory<Args, Return>( &mut self, factory_func: &'static dyn Fn<Args, Output = TransientPtr<Return>>, - ) where + ) -> error_stack::Result<(), BindingBuilderError> + where Args: 'static, Return: 'static + ?Sized, Interface: crate::interfaces::factory::IFactory<Args, Return>, { let factory_impl = CastableFactory::new(factory_func); - self.di_container.bindings.set::<Interface>(Box::new( - crate::provider::FactoryProvider::new(crate::ptr::FactoryPtr::new( - factory_impl, - )), - )); + self.di_container + .bindings + .set::<Interface>(Box::new(crate::provider::FactoryProvider::new( + crate::ptr::FactoryPtr::new(factory_impl), + ))) + .ok_or_else(|| { + report!(BindingBuilderError).attach_printable(format!( + "Binding already exists for interface '{}'", + type_name::<Interface>() + )) + })?; + + Ok(()) } } |