1 unstable release

0.1.1 Mar 27, 2024

#693 in Rust patterns

Download history 105/week @ 2024-03-22 36/week @ 2024-03-29 7/week @ 2024-04-05

148 downloads per month

MIT license

8KB
83 lines

instancebuilder

Handy solution for dependency injection in Rust.

Installation

cargo add instancebuilder

Examples

Simple

use ::std::convert::Infallible;
use ::instancebuilder::{Error, InstanceBuilder, FromInstanceBuilder};

// Example set of data of any type. Must implement Send + Sync to be threadsafe.
struct TestConfig {
    key: String,
}

// Your implementation that needs to get build.
struct TestImplementation {
    message: String,
}

impl FromInstanceBuilder for TestImplementation {
    fn try_from_builder(builder: &InstanceBuilder) -> Result<Self, Error> {
        // Put here the code necessary to build the instance
        let config: &TestConfig = builder.data()?;

        Ok(Self {
            message: config.key.clone(),
        })
    }
}

fn main() {
    // Test object to inject. This can be a database pool or a shared instance of something
    let config = TestConfig {
        key: String::from("help me!"),
    };

    let mut  builder = InstanceBuilder::new();
    // Add dependency object to the builder
    builder.insert(config);

    // Build instance of the implementation
    // dependencies are injected by the `FromInstanceBuilder` trait implementation
    let instance = builder.build::<TestImplementation>().unwrap();
}

Nested dependencies

use ::std::convert::Infallible;
use ::instancebuilder::{Error, InstanceBuilder, FromInstanceBuilder};

// Example set of data of any type. Must implement Send + Sync to be threadsafe.
struct TestConfig {
    key: String,
}

// Nested dependent struct
struct InnerTestImplementation {
    message: String,
}

impl FromInstanceBuilder for InnerTestImplementation {
    fn try_from_builder(builder: &InstanceBuilder) -> Result<Self, Error> {
        // Put here the code necessary to build the instance
        // the builder instance contains the initialized data
        let config: &TestConfig = builder.data()?;
        
        Ok(Self {
            message: config.key.clone(),
        })
    }
}

// Outer struct that depends on the nested one
struct OuterTestImplementation {
    inner: InnerTestImplementation,
}

impl FromInstanceBuilder for OuterTestImplementation {
    fn try_from_builder(builder: &InstanceBuilder) -> Result<Self, Error> {
        // Put here the code necessary to build the instance
        Ok(Self {
            // Builds dependency `InnerTestImplementation`
            inner: builder.build()?,
        })
    }
}

fn main() {
    // Test object to inject. This can be a database pool or a shared instance of something
    let config = TestConfig {
        key: String::from("help me!"),
    };

    let mut  builder = InstanceBuilder::new();
    // Add dependency object to the builder
    builder.insert(config);

    // Build instance of the implementation
    // dependencies are injected by the `FromInstanceBuilder` trait implementation
    let instance = builder.build::<OuterTestImplementation>().unwrap();
}

No runtime deps