Handling optional fields in fx.Decorate
mehdihadeli opened this issue · 3 comments
Hi,
Is there any way for handling optional input parameter in fx.decorate
method?
Actually, I'm looking for a way if, in one of my sub module
s, one dependency like *Test
not provided, I can instantiate it; otherwise, I want to return an existing register object.
fx.New(
fx.Decorate(func(l TestParam) *Test {
if l.TestData == nil {
return &Test{Name: "Test " + l.TestData.Name}
}
return l.TestData
},
),
fx.Invoke(func(t *Test) {
fmt.Print(t.Name)
}),
).Run()
type TestParam struct {
fx.In
TestData *Test `optional:"true"`
}
Error:
missing type:
- *main.Test (did you mean to Provide it?)
Hi @mehdihadeli , thanks for submitting an issue.
Decorators actually allow optional dependencies with optional
tag.
The issue in your code is because your Invoke
needs a Test
type that isn't provided any provider yet. A decorator cannot be a provider at the same time. You need to specify a provider that knows how to instantiate a Test
type into the object graph.
Hi @sywhang, thanks for your quick response.
I'm looking for a way that if one struct like Test
is not registered in the outer modules
, my inner module
can register this dependency itself. Maybe this is not possible with decorator. Is there any solution here?
For example, our inner module needed a logger, and I want the inner module to check if it is not provided and then register it.
@mehdihadeli Might be a better way to do this, but off the top of my head, you can accomplish this by using a name tag for the final logger you want to use. Something like:
type LoggerParams struct {
fx.In
Logger *zap.Logger `optional:"true"`
}
type TestParams struct {
fx.In
Logger *zap.Logger `name:"finallogger"`
}
func main() {
fx.New(
fx.Provide(
fx.Annotate(
func(p LoggerParams) (*zap.Logger, error) {
if p.Logger != nil {
return p.Logger, nil
}
return zap.NewDevelopment()
},
fx.ResultTags(`name:"finallogger"`),
),
),
fx.Invoke(func(p TestParams) {
p.Logger.Info("log message")
}),
)
}
Then if a logger is already provided it will be passed along as finallogger
, otherwise a new one will be created. In this simple case you can also just remove the XParams
structs and just use fx.Annotate
and fx.ParamTags
/fx.ResultTags
, but this is assuming you have other params for the functions.