Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/illuin-tech/goinject

go 1.24.0

require github.com/stretchr/testify v1.10.0
require github.com/stretchr/testify v1.11.1

require (
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
19 changes: 10 additions & 9 deletions injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,22 @@ type Injector struct {

// NewInjector builds up a new Injector out of a list of Modules with singleton scope
func NewInjector(options ...Option) (*Injector, error) {
mod := &configuration{
bindings: make(map[*binding]bool),
scopes: make(map[string]Scope),
conf := &configuration{
bindings: []*binding{},
scopes: make(map[string]Scope),
knownProviders: []*provideOption{},
}

for _, o := range options {
err := o.apply(mod)
for _, option := range options {
err := option.apply(conf)
if err != nil {
return nil, err
}
}

singletonScope := newSingletonScope()
mod.scopes[Singleton] = singletonScope
mod.scopes[PerLookUp] = newPerLookUpScope()
conf.scopes[Singleton] = singletonScope
conf.scopes[PerLookUp] = newPerLookUpScope()

injector := &Injector{
bindings: make(map[reflect.Type]map[string][]*binding),
Expand All @@ -49,8 +50,8 @@ func NewInjector(options ...Option) (*Injector, error) {
scope: Singleton,
}

injector.scopes = mod.scopes
for b := range mod.bindings {
injector.scopes = conf.scopes
for _, b := range conf.bindings {
_, ok := injector.bindings[b.typeof]
if !ok {
injector.bindings[b.typeof] = make(map[string][]*binding)
Expand Down
28 changes: 28 additions & 0 deletions injector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -685,3 +685,31 @@ func TestInjectorConfigurationError(t *testing.T) {
)
})
}

func TestNewInjectorShouldIgnoreMultipleBindings(t *testing.T) {
provider := Provide(func() int { return 32 })

inj, err := NewInjector(
provider,
provider,
)
assert.Nil(t, err)
err = inj.Invoke(context.Background(), func(val int) {
assert.Equal(t, 32, val)
})
assert.Nil(t, err)
}

func TestNewInjectorShouldIgnoreMultipleBindingsInDifferentModules(t *testing.T) {
sharedModule := Module("shared", Provide(func() int { return 32 }))

inj, err := NewInjector(
Module("module-A", sharedModule),
Module("module-B", sharedModule),
)
assert.Nil(t, err)
err = inj.Invoke(context.Background(), func(val int) {
assert.Equal(t, 32, val)
})
assert.Nil(t, err)
}
14 changes: 11 additions & 3 deletions module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package goinject
import (
"fmt"
"reflect"
"slices"
)

type configuration struct {
bindings map[*binding]bool
scopes map[string]Scope
bindings []*binding
scopes map[string]Scope
knownProviders []*provideOption
}

// Option enable to configure the given injector
Expand Down Expand Up @@ -47,6 +49,12 @@ type provideOption struct {
}

func (o *provideOption) apply(mod *configuration) error {
if slices.Contains(mod.knownProviders, o) {
// already registered, ignore
return nil
}
mod.knownProviders = append(mod.knownProviders, o)

if o.constructor == nil {
return newInjectorConfigurationError("cannot accept nil provider", nil)
}
Expand Down Expand Up @@ -77,7 +85,7 @@ func (o *provideOption) apply(mod *configuration) error {
}
}

mod.bindings[b] = true
mod.bindings = append(mod.bindings, b)
return nil
}

Expand Down