aboutsummaryrefslogtreecommitdiff
path: root/src/di_container.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-08-20 17:08:58 +0200
committerHampusM <hampus@hampusmat.com>2022-08-21 18:17:50 +0200
commitb31422d48a600ccccb682567f5eb11fc0bca547c (patch)
treefe3618522478249ef56c955e870e6525053f8ffa /src/di_container.rs
parentb749754dc1818a95e0baf0214b969fb99df4e7ab (diff)
feat: allow bind interface to default factory
This commit will allow interface traits to be bound to default factories. Default factories being factories that doesn't take any arguments
Diffstat (limited to 'src/di_container.rs')
-rw-r--r--src/di_container.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/di_container.rs b/src/di_container.rs
index eaa0366..84fb9e0 100644
--- a/src/di_container.rs
+++ b/src/di_container.rs
@@ -181,6 +181,39 @@ where
Ok(())
}
+
+ /// Creates a binding of type `Interface` to a factory that takes no arguments
+ /// inside of the 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_default_factory<Return>(
+ &mut self,
+ factory_func: &'static dyn Fn<(), Output = TransientPtr<Return>>,
+ ) -> error_stack::Result<(), BindingBuilderError>
+ where
+ Return: 'static + ?Sized,
+ {
+ 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),
+ )))
+ .ok_or_else(|| {
+ report!(BindingBuilderError).attach_printable(format!(
+ "Binding already exists for interface '{}'",
+ type_name::<Interface>()
+ ))
+ })?;
+
+ Ok(())
+ }
}
/// Dependency injection container.
@@ -290,6 +323,17 @@ impl DIContainer
.map_err(unable_to_cast_binding::<Interface>);
}
+ #[cfg(feature = "factory")]
+ if let Providable::Factory(binding_factory) = binding_providable {
+ use crate::interfaces::factory::IFactory;
+
+ let factory = binding_factory
+ .cast::<dyn IFactory<(), Interface>>()
+ .map_err(unable_to_cast_binding::<Interface>)?;
+
+ return Ok(factory());
+ }
+
Err(report!(DIContainerError).attach_printable(format!(
"Binding for interface '{}' is not transient",
type_name::<Interface>()