//! Blocking dependency injection container. //! //! # Examples //! ``` //! use std::collections::HashMap; //! use std::error::Error; //! //! use syrette::di_container::blocking::IDIContainer; //! use syrette::{injectable, DIContainer}; //! //! trait IDatabaseService //! { //! fn get_all_records(&self, table_name: String) -> HashMap; //! } //! //! struct DatabaseService {} //! //! #[injectable(IDatabaseService)] //! impl DatabaseService //! { //! fn new() -> Self //! { //! Self {} //! } //! } //! //! impl IDatabaseService for DatabaseService //! { //! fn get_all_records(&self, table_name: String) -> HashMap //! { //! // Do stuff here //! HashMap::::new() //! } //! } //! //! fn main() -> Result<(), Box> //! { //! let mut di_container = DIContainer::new(); //! //! di_container //! .bind::() //! .to::() //! .map_err(|err| err.to_string())?; //! //! let database_service = di_container //! .get::() //! .map_err(|err| err.to_string())? //! .transient()?; //! //! Ok(()) //! } //! ``` use std::any::type_name; use std::cell::RefCell; use std::rc::Rc; use crate::di_container::binding_storage::DIContainerBindingStorage; use crate::di_container::blocking::binding::builder::BindingBuilder; use crate::di_container::BindingOptions; use crate::errors::di_container::DIContainerError; use crate::private::cast::boxed::CastBox; use crate::private::cast::rc::CastRc; use crate::provider::blocking::{IProvider, Providable}; use crate::ptr::SomePtr; use crate::util::use_double; use_double!(crate::dependency_history::DependencyHistory); pub mod binding; pub mod prelude; /// Blocking dependency injection container interface. /// /// **This trait is sealed and cannot be implemented for types outside this crate.** 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; /// Returns the type bound with `Interface` where the binding has the specified /// options. /// /// `dependency_history` is passed to the bound type when it is being resolved. /// /// # Errors /// Will return `Err` if: /// - No binding for `Interface` exists /// - Resolving the binding for `Interface` fails /// - Casting the binding for `Interface` fails /// /// # Examples /// ```no_run /// # use syrette::di_container::blocking::DIContainer; /// # use syrette::di_container::blocking::IDIContainer; /// # use syrette::dependency_history::DependencyHistory; /// # use syrette::di_container::BindingOptions; /// # /// # struct EventHandler {} /// # struct Button {} /// # /// # fn main() -> Result<(), Box> { /// # let di_container = DIContainer::new(); /// # /// let mut dependency_history = DependencyHistory::new(); /// /// dependency_history.push::(); /// /// di_container.get_bound::