do
do copied to clipboard
`InvokeAs` problems
- Can't invoke
interface
(can't castnil
)
package main
import "github.com/samber/do/v2"
func main() {
type I interface{}
i := do.New()
do.ProvideValue(i, I("some"))
do.MustInvokeAs[I](i)
}
// panic: DI: could not find service `*main.I`, available services: `*main.I`
- Random invoked, other not checked (https://github.com/samber/do/pull/45#issuecomment-2079226572)
package main
import (
"fmt"
"github.com/samber/do/v2"
)
type I interface{ Name() string }
type i struct{}
func (i) Name() string { return "EXPECTED" }
type other struct{}
func (other) Other() {}
func (other) Name() string { return "OTHER" }
// type
func main() {
scope := do.New()
do.ProvideValue(scope, other{})
do.ProvideValue(scope, i{})
for range 10 {
fmt.Println(do.MustInvokeAs[I](scope).Name())
}
// output: something like
// OTHER
// OTHER
// OTHER
// EXPECTED
// OTHER
// OTHER
// OTHER
// EXPECTED
// OTHER
// OTHER
}
I create a function that would temporarily delete InvokedAs result by OverrideNamedValue and tried to check the next not exist.
But I came across both 1 problem and https://github.com/samber/go-type-to-string/issues/2
1- I think you should just call do.Invoke[I]
instead of do.InvokeAs[i]
, since your not performing interface matching here. I will improve the error message.
2- I'm not sure to understand the issue here. Your example output seems valid to me.
While i review comments on #45, I'm linking your issue to https://github.com/samber/do/pull/45#issuecomment-1993706391
To describe the feedback from @mbark:
- We provide
*MyServiceImplem
- Then invoke
IMyService
- We implement a
*MyServiceMock
via an override for test purposes.
Problem: do.InvokeAs
will pick a random implementation of IMyService
Possible solutions:
- invoke the latest injected service -> I don't like it, since the service injection order might be non-determinist
- use
do.OverrideNamedValue(i, do.NameOf[IMyService](), NewMyServiceMock)
-> not developer friendly - use explicit aliases:
do.AsNamed()
-> might trigger error on override
@d-enk suggested reporting an error when multiple services match the interface.
Also, I would point out that since services injected in IoC containers are opaque, invoking an interface instead of a struct might lead to loading the wrong service if method signatures overlap. In that situation, an explicit alias is safer: do.AsNamed()
Another option, maybe you just need a separate method that returns a list of all match?
And in InvokeAs
allow only one
looks like related https://github.com/samber/do/issues/33
to fix 1 problem https://github.com/samber/do/issues/81