Skip to content

Commit

Permalink
♻️ (SINGLETON) Add support to singletons
Browse files Browse the repository at this point in the history
  • Loading branch information
Vitor Hugo committed Sep 8, 2023
1 parent c36900a commit 67cdfa2
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
9 changes: 9 additions & 0 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
// Container holds the registered factories for dependency resolution.
type Container struct {
providers map[reflect.Type]reflect.Value
instances map[reflect.Type]reflect.Value
}

// New initializes and returns a new instance of the Container.
Expand All @@ -18,9 +19,11 @@ type Container struct {
// c := zeus.New()
func New() *Container {
providers := make(map[reflect.Type]reflect.Value, 0)
instances := make(map[reflect.Type]reflect.Value, 0)

container := new(Container)
container.providers = providers
container.instances = instances

return container
}
Expand Down Expand Up @@ -67,6 +70,10 @@ func (c *Container) resolve(t reflect.Type, stack []reflect.Type) (reflect.Value
return reflect.Value{}, CyclicDependencyError{TypeName: t.Name()}
}

if instance, exists := c.instances[t]; exists {
return instance, nil
}

provider, ok := c.providers[t]

if !ok {
Expand All @@ -93,6 +100,8 @@ func (c *Container) resolve(t reflect.Type, stack []reflect.Type) (reflect.Value
return reflect.Value{}, results[1].Interface().(error)
}

c.instances[t] = results[0]

return results[0], nil
}

Expand Down
34 changes: 34 additions & 0 deletions container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,40 @@ func TestContainer(t *testing.T) {

assert.ErrorContains(t, err, "some error")
})

t.Run("Shared Instance Between Dependencies", func(t *testing.T) {
c := New()

type ServiceC struct{}
type ServiceB struct {
C *ServiceC
}
type ServiceA struct {
C *ServiceC
}

c.Provide(func() *ServiceC {
return &ServiceC{}
})
c.Provide(func(c *ServiceC) *ServiceA {
return &ServiceA{C: c}
})
c.Provide(func(c *ServiceC) *ServiceB {
return &ServiceB{C: c}
})

aVal, _ := c.resolve(reflect.TypeOf(&ServiceA{}), nil)
bVal, _ := c.resolve(reflect.TypeOf(&ServiceB{}), nil)

a, ok := aVal.Interface().(*ServiceA)
assert.Equal(t, ok, true)

b, ok := bVal.Interface().(*ServiceB)
assert.Equal(t, ok, true)

assert.Equal(t, a.C, b.C)
})

})

t.Run("Run", func(t *testing.T) {
Expand Down

0 comments on commit 67cdfa2

Please sign in to comment.