Skip to content
This repository was archived by the owner on Jan 18, 2021. It is now read-only.

Commit 6dc5729

Browse files
author
Maxim Bovtunov
authored
Merge pull request #35 from defval/parameter-bag
Parameter bag, improve docs
2 parents cd61cef + 5b860a1 commit 6dc5729

File tree

9 files changed

+208
-85
lines changed

9 files changed

+208
-85
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ You can see latest `v1`
2323
## Contents
2424

2525
- [Installing](#installing)
26+
- [Getting Started](#getting-started)
2627
- [Tutorial](#tutorial)
2728
- [Providing](#providing)
2829
- [Extraction](#extraction)
@@ -31,6 +32,7 @@ You can see latest `v1`
3132
- [Advanced features](#advanced-features)
3233
- [Named definitions](#named-definitions)
3334
- [Optional parameters](#optional-parameters)
35+
- [Parameter Bag](#parameter-bag)
3436
- [Prototypes](#prototypes)
3537
- [Cleanup](#cleanup)
3638
- [Contributing](#contributing)
@@ -41,6 +43,10 @@ You can see latest `v1`
4143
go get -u github.com/defval/inject/v2
4244
```
4345

46+
## Getting Started
47+
48+
49+
4450
## Tutorial
4551

4652
Let's learn to use `inject` by example. We will code a simple
@@ -342,6 +348,10 @@ type ServiceParameter struct {
342348
}
343349
```
344350

351+
### Parameter Bag
352+
353+
TBD
354+
345355
### Prototypes
346356

347357
If you want to create a new instance on each extraction use

container.go

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func New(options ...Option) *Container {
2222

2323
// Container is a dependency injection container.
2424
type Container struct {
25-
providers []*providerOptions
25+
providers []di.ProvideParams
2626
container *di.Container
2727
}
2828

@@ -36,34 +36,26 @@ type Container struct {
3636
// If the target type does not exist in a container or instance type building failed, Extract() returns an error.
3737
// Use ExtractOption for modifying the behavior of this function.
3838
func (c *Container) Extract(target interface{}, options ...ExtractOption) (err error) {
39-
var po = &extractOptions{
40-
target: target,
39+
var params = di.ExtractParams{
40+
Target: target,
4141
}
4242

4343
// apply extract options
4444
for _, opt := range options {
45-
opt.apply(po)
45+
opt.apply(&params)
4646
}
4747

48-
return c.container.Extract(di.ExtractParams{
49-
Name: po.name,
50-
Target: target,
51-
})
48+
return c.container.Extract(params)
5249
}
5350

54-
// Cleanup
51+
// Cleanup cleanup container.
5552
func (c *Container) Cleanup() {
5653
c.container.Cleanup()
5754
}
5855

5956
func (c *Container) compile() {
6057
for _, po := range c.providers {
61-
c.container.Provide(di.ProvideParams{
62-
Name: po.name,
63-
Provider: po.provider,
64-
Interfaces: po.interfaces,
65-
IsPrototype: po.prototype,
66-
})
58+
c.container.Provide(po)
6759
}
6860

6961
c.container.Compile()

di/container.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,31 @@ type ProvideParams struct {
2929
Name string
3030
Provider interface{}
3131
Interfaces []interface{}
32+
Parameters ParameterBag
3233
IsPrototype bool
3334
}
3435

3536
// Provide adds constructor into container with parameters.
3637
func (c *Container) Provide(params ProvideParams) {
37-
var provider provider = createConstructor(params.Name, params.Provider)
38-
k := provider.resultKey()
38+
prov := provider(createConstructor(params.Name, params.Provider))
39+
k := prov.resultKey()
3940

4041
if c.exists(k) {
41-
panicf("The `%s` type already exists in container", provider.resultKey())
42+
panicf("The `%s` type already exists in container", prov.resultKey())
4243
}
4344

4445
if !params.IsPrototype {
45-
provider = asSingleton(provider)
46+
prov = asSingleton(prov)
4647
}
4748

48-
c.addProvider(provider)
49-
c.provideEmbedParameters(provider)
49+
c.addProvider(prov)
50+
c.provideEmbedParameters(prov)
51+
52+
parameterBugProvider := createParameterBugProvider(k, params.Parameters)
53+
c.addProvider(parameterBugProvider)
5054

5155
for _, iface := range params.Interfaces {
52-
c.processProviderInterface(provider, iface)
56+
c.processProviderInterface(prov, iface)
5357
}
5458
}
5559

di/container_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ func TestContainerProvide(t *testing.T) {
157157
cleanup := func() {}
158158
c.MustProvide(ditest.CreateFooConstructorWithCleanup(cleanup))
159159
})
160+
160161
}
161162

162163
func TestContainerExtract(t *testing.T) {
@@ -248,6 +249,50 @@ func TestContainerExtract(t *testing.T) {
248249

249250
c.MustNotEqualPointer(extracted1, extracted2)
250251
})
252+
253+
t.Run("container extract correct parameter bag for type", func(t *testing.T) {
254+
c := NewTestContainer(t)
255+
256+
c.Provide(di.ProvideParams{
257+
Provider: ditest.NewFooWithName,
258+
Parameters: di.ParameterBag{
259+
"name": "test",
260+
},
261+
})
262+
263+
c.MustCompile()
264+
265+
var foo *ditest.Foo
266+
err := c.Extract(di.ExtractParams{
267+
Target: &foo,
268+
})
269+
270+
require.NoError(t, err)
271+
require.Equal(t, "test", foo.Name)
272+
})
273+
274+
t.Run("container extract correct parameter bag for type", func(t *testing.T) {
275+
c := NewTestContainer(t)
276+
277+
c.Provide(di.ProvideParams{
278+
Name: "named",
279+
Provider: ditest.NewFooWithName,
280+
Parameters: di.ParameterBag{
281+
"name": "test",
282+
},
283+
})
284+
285+
c.MustCompile()
286+
287+
var foo *ditest.Foo
288+
err := c.Extract(di.ExtractParams{
289+
Name: "named",
290+
Target: &foo,
291+
})
292+
293+
require.NoError(t, err)
294+
require.Equal(t, "test", foo.Name)
295+
})
251296
}
252297

253298
func TestContainerResolve(t *testing.T) {

di/internal/ditest/foo.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
package ditest
22

3+
import "github.com/defval/inject/v2/di"
4+
35
// Foo test struct
4-
type Foo struct{}
6+
type Foo struct {
7+
Name string
8+
}
59

610
// NewFoo create new foo
711
func NewFoo() *Foo {
812
return &Foo{}
913
}
1014

15+
// NewFooWithName
16+
func NewFooWithName(parameters di.ParameterBag) *Foo {
17+
return &Foo{Name: parameters.RequireString("name")}
18+
}
19+
1120
// NewCycleFooBar
1221
func NewCycleFooBar(bar *Bar) *Foo {
1322
return &Foo{}

di/parameter_bag.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package di
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
)
7+
8+
// createParameterBugProvider
9+
func createParameterBugProvider(key key, parameters ParameterBag) provider {
10+
return createConstructor(key.String(), func() ParameterBag { return parameters })
11+
}
12+
13+
// Parameters
14+
type ParameterBag map[string]interface{}
15+
16+
// String
17+
func (b ParameterBag) RequireString(key string) string {
18+
value, ok := b[key].(string)
19+
if !ok {
20+
panic(fmt.Sprintf("value for string key `%s` not found", key))
21+
}
22+
23+
return value
24+
}
25+
26+
var parameterBagType = reflect.TypeOf(ParameterBag{})

di/provider_ctor.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,17 @@ func (c constructorProvider) parameters() parameterList {
8383

8484
for i := 0; i < c.ctor.NumIn(); i++ {
8585
ptype := c.ctor.In(i)
86+
var pname string
87+
88+
if ptype == parameterBagType {
89+
pname = c.resultKey().String()
90+
}
8691

8792
p := parameter{
88-
key: key{typ: ptype},
93+
key: key{
94+
name: pname,
95+
typ: ptype,
96+
},
8997
optional: false,
9098
embed: isEmbedParameter(ptype),
9199
}

0 commit comments

Comments
 (0)