samber / do

⚙️ A dependency injection toolkit based on Go 1.18+ Generics.
https://pkg.go.dev/github.com/samber/do
MIT License
1.69k stars 65 forks source link

Proposal: way to automate invoke deps in do.Provider for any type constructor #67

Open d-enk opened 2 months ago

d-enk commented 2 months ago
package main

import "github.com/samber/do/v2"

type Type struct {
    int
    uint64
    string
}

func NewType(i int, u uint64, s string) Type {
    return Type{i, u, s}
}

func main() {
    scope := do.New()

    do.ProvideValue(scope, int(1))
    do.ProvideValue(scope, uint64(2))
    do.ProvideValue(scope, string("str"))

    // instead
    do.Provide(scope, func(i do.Injector) (Type, error) {
        return NewType(
            do.MustInvoke[int](i),
            do.MustInvoke[uint64](i),
            do.MustInvoke[string](i),
        ), nil
    })

    // something like
    do.ProvideAny[Type](scope, NewType)

    _ = do.MustInvoke[Type](scope)
}

Where

func ProvideAny[T any](i do.Injector, fun any) {
    fn := reflect.ValueOf(fun)

    // check that fn is func(...) T or func(...) (T, error)

    do.Provide[T](i, func(i do.Injector) (res T, err error) {
        inputTypes := []reflect.Value{}
        // inputTypes - invoked input by type name

        out := fn.Call(inputTypes)

        // res = out[0]
        // err = out[1]

        return
    })
}

Also the function can have variadic names ... string With a match for each function parameter, to use it instead of the type name. Analog do:"name" in struct

If interested I can send pull request. We can discuss the interface.

Now it just

func ToProvider[T any](fun any) do.Provider[T]

do.Provide(scope, ToProvider[Type](NewType))
samber commented 2 months ago

Yes, it has been discussed already.

I'm adding this proposal to v2.1 release.

See https://github.com/samber/do/pull/28

d-enk commented 2 months ago

Yes, it has been discussed already.

There is nothing about calculating constructor function arguments.

Here we are talking about the possibility of turning a "native" constructor into Provider