Giter Club home page Giter Club logo

Comments (5)

defval avatar defval commented on August 18, 2024

Hi again, @fionera!

Your code might look like this:

package main

import (
	"fmt"
	"log"

	"github.com/goava/di"
)

type Configuration struct {
	Enabled bool
}

func NewConfiguration() *Configuration {
	return &Configuration{Enabled: true}
}

func main() {
	var conf *Configuration
	container, err := di.New(
		di.Provide(NewConfiguration),
		di.Resolve(&conf),
	)
	if err != nil {
		log.Fatal(err)
	}
	if conf.Enabled {
		if err := container.Invoke(func() { fmt.Println("Hello World") }); err != nil {
			log.Fatal(err)
		}
	}
}

If we are talking about providing depending on the availability of a certain type:

package main

import (
	"log"
	"net/http"

	"github.com/goava/di"
)

func NewHTTPServer(mux http.Handler) *http.Server {
	return &http.Server{
		Handler: mux,
	}
}

func main() {
	container, err := di.New(
		di.Provide(http.NewServeMux, di.As(new(http.Handler))), // if comment on this, the server will not be provided
		di.WithCompile(), // eject compilation stage
	)
	if err != nil {
		log.Fatal(err)
	}
	var handler http.Handler
	if container.Has(&handler) { // checking for a handler
		if err := container.Provide(NewHTTPServer); err != nil { // provide if handler exists
			log.Fatal(err)
		}
	}
	if err := container.Compile(); err != nil {
		log.Fatal(err)
	}
	var server *http.Server
	if err := container.Resolve(&server); err != nil {
		log.Fatal(err) // server not provided
	} else {
		log.Println("Server resolved")
	}
}

But if you need to provide type depending on the already initialized instance:

type Configuration struct {
 	 Enabled bool
}

di.New(
di.Provide(func () *Configuration {
		return &Configuration{ true }
}),
di.Provide(func(configuration *Configuration) di.Option {
	if configuration.Enabled {
		return di.Provide(NewMyType) // Provide instead Invoke
	}
		return nil
})
)

In this example configuration already built and Provide() breaks the order of building the dependency graph.

Modifying an already compiled graph is a bad way and intentionally impossible. This can cause unnecessary side effects.

I want to keep container workaround strictly consistent:

  • building: available Provide() and Has() methods;
  • compilation: parses dependencies params, build dependency graph and check that it is correct;
  • interaction: available Invoke(), Resolve() and Has() method.

If you describe your real problem in more detail, we will find a solution.

from di.

fionera avatar fionera commented on August 18, 2024

This feature is easier to understand when used with #4.

I have a interface I implement with different config backends. Depending on the Environment, one of these will get added to the Container and Provide it. All Modules in this Application are Providing their own Configuration struct and as construtor field have the Config interface.
This way all Configurations structs are getting filled by the correct Config backend. I also have Provides that depend on this Configuration Struct and returns more Options, like Provide and Invokes, like how they are in fx, to the Container/App.

This way I can enable parts of the App by changing the Config and only ever interact with the parsed config struct without being verbose or having any connection between the config system and the fact that smth is enabled.

from di.

defval avatar defval commented on August 18, 2024

@fionera Can you provide a library from another language with similar functionality so that I can research it? I'm sure there are a lot of pitfalls here.

from di.

fionera avatar fionera commented on August 18, 2024

Ive implemented it into fx myself and didnt found anything that could be a pitfall. You basically split up the handling of Provide entries in the Compile process. fionera/fx@c2d9ca7

from di.

fionera avatar fionera commented on August 18, 2024

If you want I can port this to di and make a PR

from di.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.