How to improve ergomonics of that generic DI attempt

Hello, I found an interesting library for dependency injection, but the need to write those I1, I2, I3 (inference stuff) is a deal breaker for me. If not the need to write an infer generic for each dep, we could've used this approach!

Do you have any ideas on how to make it more usable?

The core problem is that I will need to add new I_n to all types on the tree If I would need a new type at the leaf, instead of adding it only on the bottom and then writing add_instance on the top. Bounded refactor

Related: Pre-pre-RFC/Working Prototype: Borrow-Aware Automated Context Passing - language design - Rust Internals

use teloc::*;

struct Resource1(i32);
struct Resource2(i32);
struct Resource3<'a>(&'a i32);

fn main() {
    let s = ServiceProvider::new()
        .add_instance(&Resource1(1))
        .add_instance(&Resource2(2))
        .add_instance(&Resource3(&3));

    link(&s);
    link(&s);
}

trait Resource<'a, I, T: 'a>: Resolver<'a, &'a InstanceContainer<&'a T>, &'a T, I> {}

impl<'a, I, T: 'a, R> Resource<'a, I, T> for R where
    R: Resolver<'a, &'a InstanceContainer<&'a T>, &'a T, I>
{
}

trait Link<'a, I1, I2, I3>: User1<'a, I1> + User2<'a, I2> + User3<'a, I3>{}
impl<'a, T: 'a, I1, I2, I3> Link<'a, I1, I2, I3> for T where T: User1<'a, I1> + User2<'a, I2> + User3<'a, I3>{}

fn link<'a, P, C, I1, I2, I3>(s: &'a ServiceProvider<P, C>)
where
    ServiceProvider<P, C>: Link<'a, I1, I2, I3>,
{
    user1(&s);
    user2(&s);
    user3(&s);
}

trait User1<'a, I>: Resource<'a, I, Resource1> {}
impl<'a, I, T> User1<'a, I> for T where T: Resource<'a, I, Resource1> {}

fn user1<'a, P, C, I>(s: &'a ServiceProvider<P, C>)
where
    ServiceProvider<P, C>: User1<'a, I>,
{
    let r1: &Resource1 = s.resolve();
    println!("R1: {}", r1.0);
}

trait User2<'a, I>: Resource<'a, I, Resource2> {}
impl<'a, I, T> User2<'a, I> for T where T: Resource<'a, I, Resource2> {}

fn user2<'a, P, C, I>(s: &'a ServiceProvider<P, C>)
where
    ServiceProvider<P, C>: User2<'a, I>,
{
    let r2: &Resource2 = s.resolve();
    println!("R2: {}", r2.0);
}

trait User3<'a, I>: Resource<'a, I, Resource3<'a>> {}
impl<'a, I, T> User3<'a, I> for T where T: Resource<'a, I, Resource3<'a>> {}

fn user3<'a, P, C, I>(s: &'a ServiceProvider<P, C>)
where
    ServiceProvider<P, C>: User3<'a, I>,
{
    let r3: &Resource3 = s.resolve();
    println!("R3: {}", r3.0);
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.