Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InvokeAs problems #75

Open
d-enk opened this issue May 6, 2024 · 5 comments
Open

InvokeAs problems #75

d-enk opened this issue May 6, 2024 · 5 comments
Milestone

Comments

@d-enk
Copy link

d-enk commented May 6, 2024

  1. Can't invoke interface (can't cast nil)
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`
  1. Random invoked, other not checked ([👷] Road to v2 🚀 #45 (comment))
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 samber/go-type-to-string#2

@samber
Copy link
Owner

samber commented May 7, 2024

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.

@samber samber added this to the v2 milestone May 7, 2024
@samber
Copy link
Owner

samber commented May 7, 2024

While i review comments on #45, I'm linking your issue to #45 (comment)

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

@samber
Copy link
Owner

samber commented May 7, 2024

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()

@samber samber mentioned this issue May 7, 2024
50 tasks
@d-enk
Copy link
Author

d-enk commented May 7, 2024

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 #33

@d-enk
Copy link
Author

d-enk commented May 13, 2024

to fix 1 problem #81

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants