service-rs 0.1.7

An async-first, lightweight dependency injection container for Rust
Documentation
use std::sync::Arc;

use service_rs::{Injectable, ServiceCollection};

struct SomeStringWrapper(String);

impl std::fmt::Display for SomeStringWrapper {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

struct TestDep(i32);

impl std::fmt::Display for TestDep {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[derive(Injectable)]
struct DependingDeps {
    test_dep: Arc<TestDep>,
}

impl std::fmt::Display for DependingDeps {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Hello from DependingDeps (via std::fmt::Display)")
    }
}

impl DependingDeps {
    pub fn test_dep(&self) -> &Arc<TestDep> {
        &self.test_dep
    }
}

trait SomeInterface: Send + Sync {
    fn do_something(&self);
}

#[derive(Injectable)]
struct SomeInterfaceImpl;

impl SomeInterface for SomeInterfaceImpl {
    fn do_something(&self) {
        println!("Doing something");
    }
}

#[tokio::main]
async fn main() {
    let mut collection = ServiceCollection::new();
    collection.add_singleton_with_factory::<i32, _, _>(|_| async {
        Ok(Box::new(42) as Box<dyn std::any::Any + Send + Sync>)
    });
    collection.add_transient_with_factory::<SomeStringWrapper, _, _>(|_| async {
        Ok(Box::new(SomeStringWrapper("Hello".to_string()))
            as Box<dyn std::any::Any + Send + Sync>)
    });
    collection.add_scoped_with_factory::<TestDep, _, _>(|_| async {
        Ok(Box::new(TestDep(42)) as Box<dyn std::any::Any + Send + Sync>)
    });
    collection.add_scoped::<DependingDeps>();
    collection.add_scoped_interface::<dyn SomeInterface, SomeInterfaceImpl>();

    println!("Successfully registered {} services", collection.len());

    let provider = collection.build();

    println!("Successfully built ServiceProvider");

    {
        match provider.get::<i32>().await {
            Ok(first) => println!(
                "(first get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<i32>(),
                Arc::as_ptr(&first),
                first
            ),
            Err(e) => println!(
                "(first get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<i32>(),
                e
            ),
        }

        match provider.get::<i32>().await {
            Ok(second) => println!(
                "(second get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<i32>(),
                Arc::as_ptr(&second),
                second
            ),
            Err(e) => println!(
                "(second get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<i32>(),
                e
            ),
        }
    }

    {
        match provider.get::<SomeStringWrapper>().await {
            Ok(first) => println!(
                "(first get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<SomeStringWrapper>(),
                Arc::as_ptr(&first),
                first
            ),
            Err(e) => println!(
                "(first get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<SomeStringWrapper>(),
                e
            ),
        }

        match provider.get::<SomeStringWrapper>().await {
            Ok(second) => println!(
                "(second get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<SomeStringWrapper>(),
                Arc::as_ptr(&second),
                second
            ),
            Err(e) => println!(
                "(second get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<SomeStringWrapper>(),
                e
            ),
        }
    }

    {
        match provider.get::<TestDep>().await {
            Ok(first) => println!(
                "(first get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<TestDep>(),
                Arc::as_ptr(&first),
                first
            ),
            Err(e) => println!(
                "(first get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<TestDep>(),
                e
            ),
        }

        match provider.get::<TestDep>().await {
            Ok(second) => println!(
                "(second get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<TestDep>(),
                Arc::as_ptr(&second),
                second
            ),
            Err(e) => println!(
                "(second get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<TestDep>(),
                e
            ),
        }
    }

    {
        let scope = provider.create_scope();

        match scope.get::<TestDep>().await {
            Ok(first) => println!(
                "(first get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<TestDep>(),
                Arc::as_ptr(&first),
                first
            ),
            Err(e) => println!(
                "(first get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<TestDep>(),
                e
            ),
        }

        match scope.get::<TestDep>().await {
            Ok(second) => println!(
                "(second get attempt) Service with type {} ({:p}) value is {}",
                std::any::type_name::<TestDep>(),
                Arc::as_ptr(&second),
                second
            ),
            Err(e) => println!(
                "(second get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<TestDep>(),
                e
            ),
        }

        match scope.get::<DependingDeps>().await {
            Ok(first) => println!(
                "(first get attempt) Service with type {} ({:p}) resolved successfully with test_dep at {:p}",
                std::any::type_name::<DependingDeps>(),
                Arc::as_ptr(&first),
                Arc::as_ptr(first.test_dep())
            ),
            Err(e) => println!(
                "(first get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<DependingDeps>(),
                e
            ),
        }

        match scope.get::<DependingDeps>().await {
            Ok(second) => println!(
                "(second get attempt) Service with type {} ({:p}) resolved successfully with test_dep at {:p}",
                std::any::type_name::<DependingDeps>(),
                Arc::as_ptr(&second),
                Arc::as_ptr(second.test_dep())
            ),
            Err(e) => println!(
                "(second get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<DependingDeps>(),
                e
            ),
        }
    }

    {
        match provider
            .create_scope()
            .get::<Box<dyn SomeInterface>>()
            .await
        {
            Ok(first) => {
                println!(
                    "(first get attempt) Service with type {} ({:p}) resolved successfully",
                    std::any::type_name::<Box<dyn SomeInterface>>(),
                    Arc::as_ptr(&first)
                );
                first.do_something();
            }
            Err(e) => println!(
                "(first get attempt) Failed to get service with type {}: {}",
                std::any::type_name::<Box<dyn SomeInterface>>(),
                e
            ),
        }
    }
}