noema 0.2.22

Noema IOC and DI framework for Rust
Documentation
use std::sync::Arc;

#[async_trait::async_trait]
pub trait Module: Send + Sync {
    type AppConfig;
    fn name(&self) -> &'static str {
        std::any::type_name::<Self>()
    }
    async fn init(&self) {}
    fn configure(&self, cfg: &mut Self::AppConfig);
}

pub struct Modules<TAppConfig> {
    modules: Vec<Arc<dyn Module<AppConfig = TAppConfig>>>,
}

impl<TAppConfig> Modules<TAppConfig> {
    pub fn new() -> Self {
        Self {
            modules: Vec::new(),
        }
    }

    pub fn add<TModule>(mut self) -> Self
    where
        TModule: Module<AppConfig = TAppConfig> + 'static + Default,
    {
        self.modules.push(Arc::new(TModule::default()));
        self
    }

    pub fn arc(self) -> Arc<Self> {
        Arc::new(self)
    }

    pub async fn init(&self) {
        for module in &self.modules {
            module.init().await;
        }
    }

    pub fn configure(&self, cfg: &mut TAppConfig) {
        for module in &self.modules {
            module.configure(cfg);
        }
    }
}

#[cfg(test)]
#[test]
fn modules_test() {
    use futures::executor::block_on;

    use crate::modules::*;

    #[derive(Default)]
    struct MyModule;
    impl Module for MyModule {
        type AppConfig = String;
        fn configure(&self, cfg: &mut Self::AppConfig) {
            *cfg += "Configured by MyModule. ";
            println!("Configuring MyModule");
        }
    }

    let modules = Modules::new().add::<MyModule>().arc();
    let modules_clone = modules.clone();
    block_on(async move {
        modules_clone.init().await;
    });

    block_on(async move {
        let mut config = String::new();
        modules.clone().configure(&mut config);
    });
}