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

Overriding registered implementations #230

Closed
amirov-m opened this issue Feb 20, 2019 · 2 comments
Closed

Overriding registered implementations #230

amirov-m opened this issue Feb 20, 2019 · 2 comments

Comments

@amirov-m
Copy link

Hello!
I would like to override already registered class instance with another one. For example in functional tests it is very useful to override registered instances. It seems like it is not possible to do that in current version.

Are you planning to implement this feature in the future?

@glibsm
Copy link
Collaborator

glibsm commented Feb 25, 2019

There are a few discussions on this topic in the fx repo: uber-go/fx#653

sywhang added a commit to uber-go/fx that referenced this issue Feb 10, 2022
This adds `fx.Decorate`, which lets you specify decorators to an fx app. A decorator can take in one or more dependencies that have already been `Provide`d to the app, and produce one or more values that will be used as replacements in the object graph.

For example, suppose there is a simple app like this:
```go
fx.New(
  fx.Provide(func() *Logger {
    return &Logger{Name: "logger"}
  }),
  fx.Invoke(func(l *Logger) {
    fmt.Println(l.Name)
  }),
)
```

Running this app will print "logger" on the console.

Now let us suppose a decorator was provided:
```go
fx.New(
  fx.Provide(...), // Provide same function as above
  fx.Decorate(func(l *Logger) *Logger {
    return &Logger{Name: "decorated " + l.Name}
  }),
  fx.Invoke(...), // Invoke same function as above
)
```

The decorator here will take in the provided Logger and replace it with another logger whose `Name` is `decorated logger`. The `Invoke`d function is then executed with this replacement value, so running this app will print "decorated logger" on the console.

In terms of implementation, a decorator is represented by the target decorator function and the call stack it was provided from, similar to a provider. `module` contains a list of decorators that were specified within its scope.

The dig dependency had to be updated to the latest master branch of Dig to ensure the fix for uber-go/dig#316 is in.

Following this PR, there are two additional pieces I will be adding:
1. An eventing system for fx.Decorate. 
2. fx.Replace, which takes in a value instead of a function to replace a value in the object graph. This is similar to what fx.Supply is to fx.Provide.

This PR along with the two PRs above should make the long-awaited feature of graph modifications in fx finally possible.

---

Refs #653, #649, #825, uber-go/dig#230, GO-1203, GO-736
@sywhang
Copy link
Contributor

sywhang commented Mar 1, 2022

It's been a while since this issue was opened, but we just released v1.17.0 that contains the changes to modify the registered values of the dependency graph using fx.Decorate and fx.Replace. Will close this issue now - let me know if you have questions regarding the usage of these APIs.

@sywhang sywhang closed this as completed Mar 1, 2022
luoboton added a commit to luoboton/fx that referenced this issue Aug 24, 2022
This adds `fx.Decorate`, which lets you specify decorators to an fx app. A decorator can take in one or more dependencies that have already been `Provide`d to the app, and produce one or more values that will be used as replacements in the object graph.

For example, suppose there is a simple app like this:
```go
fx.New(
  fx.Provide(func() *Logger {
    return &Logger{Name: "logger"}
  }),
  fx.Invoke(func(l *Logger) {
    fmt.Println(l.Name)
  }),
)
```

Running this app will print "logger" on the console.

Now let us suppose a decorator was provided:
```go
fx.New(
  fx.Provide(...), // Provide same function as above
  fx.Decorate(func(l *Logger) *Logger {
    return &Logger{Name: "decorated " + l.Name}
  }),
  fx.Invoke(...), // Invoke same function as above
)
```

The decorator here will take in the provided Logger and replace it with another logger whose `Name` is `decorated logger`. The `Invoke`d function is then executed with this replacement value, so running this app will print "decorated logger" on the console.

In terms of implementation, a decorator is represented by the target decorator function and the call stack it was provided from, similar to a provider. `module` contains a list of decorators that were specified within its scope.

The dig dependency had to be updated to the latest master branch of Dig to ensure the fix for uber-go/dig#316 is in.

Following this PR, there are two additional pieces I will be adding:
1. An eventing system for fx.Decorate. 
2. fx.Replace, which takes in a value instead of a function to replace a value in the object graph. This is similar to what fx.Supply is to fx.Provide.

This PR along with the two PRs above should make the long-awaited feature of graph modifications in fx finally possible.

---

Refs #653, #649, #825, uber-go/dig#230, GO-1203, GO-736
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