dig icon indicating copy to clipboard operation
dig copied to clipboard

Add API to invoke named values

Open lianzhao opened this issue 6 years ago • 5 comments

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

lianzhao avatar Feb 28 '18 03:02 lianzhao

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.

JamesArthurHolland avatar Sep 30 '19 16:09 JamesArthurHolland

It was merged in https://github.com/uber-go/dig/pull/233, but 1.8.0 has not been released

glibsm avatar Sep 30 '19 21:09 glibsm

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)

JamesArthurHolland avatar Oct 02 '19 11:10 JamesArthurHolland

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. 🤷‍♂

glibsm avatar Oct 04 '19 17:10 glibsm

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.

JamesArthurHolland avatar Oct 05 '19 16:10 JamesArthurHolland