iqlusioninc / abscissa

Application microframework with command-line option parsing, configuration, error handling, logging, and shell interactions
Apache License 2.0
574 stars 38 forks source link

Better dependency injection syntax #125

Open tarcieri opened 5 years ago

tarcieri commented 5 years ago

The current dependency injection syntax is pretty gnarly and looks like this:

#[derive(Component, Debug)]
#[component(inject = "init_foo(depname::Foo)")]
#[component(inject = "init_bar(depname::Bar)")]
pub struct MyComponent {
    pub fn init_foo(&mut self, foo: &mut depname::Foo) -> Result<(), FrameworkError> {
        [...[
    }

    pub fn init_bar(&mut self, bar: &mut depname::Bar) -> Result<(), FrameworkError> {
        [...]
    }
}

It'd be nice to be able to use an attribute macro on the "injector" functions instead. Something like this:

#[derive(Component, Debug)]
#[inject(init_foo, init_bar)]
pub struct MyComponent {
    #[inject]
    pub fn init_foo(&mut self, foo: &mut depname::Foo) -> Result<(), FrameworkError> {
        [...[
    }

    #[inject]
    pub fn init_bar(&mut self, bar: &mut depname::Bar) -> Result<(), FrameworkError> {
        [...]
    }
}

It'd be nice if the #[inject] annotations on individual functions were all that were required, but AFAICT, the #[inject(init_foo, init_bar)] is still needed to thunk between them.

toadzky commented 3 years ago

it would also be nice to have a single method that accepts multiple dependencies: inject = init(crate::Foo, crate::Bar)