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

Add API to invoke named values #181

Open
lianzhao opened this issue Feb 28, 2018 · 5 comments
Open

Add API to invoke named values #181

lianzhao opened this issue Feb 28, 2018 · 5 comments

Comments

@lianzhao
Copy link

I'd like to do something like these

c.Provide(myExporter1Ctor, dig.Name("myExporter1"))
c.Provide(myExporter2Ctor, dig.Name("myExporter2"))
err := c.Invoke(func() *exporter.Exporter {
  // ...
}, dig.Name("myExporter1"))
@JamesArthurHolland
Copy link

Has this been implemented? Are there any docs on how to use this?

It would be good to be able to use the named invocation without the use of param structs.

@glibsm
Copy link
Collaborator

glibsm commented Sep 30, 2019

It was merged in #233, but 1.8.0 has not been released

@JamesArthurHolland
Copy link

cannot use dig.Name("myExporter1") (type dig.ProvideOption) as type dig.InvokeOption in argument to container.Invoke:
dig.ProvideOption does not implement dig.InvokeOption (missing dig.unimplemented method)

@glibsm
Copy link
Collaborator

glibsm commented Oct 4, 2019

cannot use dig.Name("myExporter1") (type dig.ProvideOption) as type dig.InvokeOption in argument to container.Invoke:
dig.ProvideOption does not implement dig.InvokeOption (missing dig.unimplemented method)

The types dig.ProvideOption, part of the container.Provide, and type dig.InvokeOption, part of the container.Invoke, are different. They are strongly typed to their respective method calls, so unfortunately the same dig.Name can't be used in both call sites.

There is no corresponding inlined Invoke option, meaning you have to use fx.In on the receiving end.

The rationale here is that dig.Name allows you to use existing (even stdlib) constructors, but name their return types if you need more than one to avoid a clash.

Whenever you're writing Invoke code, the thought here is that you are writing something new and not attempting to use an existing signature or a function (mostly since returns are completely discarded).

To put what I just said in code, lets assume you have two clashing constructors (in this example returning a string) which you want to use.

package main

import (
	"fmt"

	"go.uber.org/dig"
)

func username() string {
	return "foo"
}

func password() string {
	return "bar"
}

func main() {
	c := dig.New()
	c.Provide(username, dig.Name("username"))
	c.Provide(password, dig.Name("password"))

	err := c.Invoke(func(p struct {
		dig.In

		U string `name:"username"`
		P string `name:"password"`
	}) {
		fmt.Println("user >>>", p.U)
		fmt.Println("pwd  >>>", p.P)
	})
	if err != nil {
		panic(err)
	}
}

If you have ideas of a shorthand InvokeOption that will mirror the dig.Name, PRs are always welcome :)

Perhaps dig.Named can be an option. You provide something with a name, and you invoked a named something. 🤷‍♂

@JamesArthurHolland
Copy link

I think dig.Name should be both an Invoke and Provide option, I had a look at the code but it's too much for me to change right now. Doing a tech test.

Decided to use https://github.com/sarulabs/di instead, they are doing named invocation nicely.

tylersouthwick added a commit to tylersouthwick/dig that referenced this issue Oct 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants