33package container
44
55import (
6- "reflect "
6+ internal "github.com/golobby/container/pkg/container "
77)
88
9- // invoke will call the given function and return its returned value.
10- // It only works for functions that return a single value.
11- func invoke (function interface {}) interface {} {
12- return reflect .ValueOf (function ).Call (arguments (function ))[0 ].Interface ()
9+ func NewContainer () internal.Container {
10+ return make (internal.Container )
1311}
1412
15- // binding keeps a binding resolver and instance (for singleton bindings).
16- type binding struct {
17- resolver interface {} // resolver function
18- instance interface {} // instance stored for singleton bindings
19- }
20-
21- // resolve will return the concrete of related abstraction.
22- func (b binding ) resolve () interface {} {
23- if b .instance != nil {
24- return b .instance
25- }
26-
27- return invoke (b .resolver )
28- }
29-
30- // container is the IoC container that will keep all of the bindings.
31- var container = map [reflect.Type ]binding {}
32-
33- // bind will map an abstraction to a concrete and set instance if it's a singleton binding.
34- func bind (resolver interface {}, singleton bool ) {
35- resolverTypeOf := reflect .TypeOf (resolver )
36- if resolverTypeOf .Kind () != reflect .Func {
37- panic ("the resolver must be a function" )
38- }
39-
40- for i := 0 ; i < resolverTypeOf .NumOut (); i ++ {
41- var instance interface {}
42- if singleton {
43- instance = invoke (resolver )
44- }
45-
46- container [resolverTypeOf .Out (i )] = binding {
47- resolver : resolver ,
48- instance : instance ,
49- }
50- }
51- }
52-
53- // arguments will return resolved arguments of the given function.
54- func arguments (function interface {}) []reflect.Value {
55- functionTypeOf := reflect .TypeOf (function )
56- argumentsCount := functionTypeOf .NumIn ()
57- arguments := make ([]reflect.Value , argumentsCount )
58-
59- for i := 0 ; i < argumentsCount ; i ++ {
60- abstraction := functionTypeOf .In (i )
13+ // A default instance for container
14+ var container internal.Container = internal .NewContainer ()
6115
62- var instance interface {}
63-
64- if concrete , ok := container [abstraction ]; ok {
65- instance = concrete .resolve ()
66- } else {
67- panic ("no concrete found for the abstraction: " + abstraction .String ())
68- }
69-
70- arguments [i ] = reflect .ValueOf (instance )
71- }
72-
73- return arguments
74- }
75-
76- // Singleton will bind an abstraction to a concrete for further singleton resolves.
77- // It takes a resolver function which returns the concrete and its return type matches the abstraction (interface).
78- // The resolver function can have arguments of abstraction that have bound already in Container.
16+ // Singleton creates a singleton for the default instance.
7917func Singleton (resolver interface {}) {
80- bind (resolver , true )
18+ container . Singleton (resolver )
8119}
8220
83- // Transient will bind an abstraction to a concrete for further transient resolves.
84- // It takes a resolver function which returns the concrete and its return type matches the abstraction (interface).
85- // The resolver function can have arguments of abstraction that have bound already in Container.
21+ // Transient creates a transient binding for the default instance.
8622func Transient (resolver interface {}) {
87- bind (resolver , false )
23+ container . Transient (resolver )
8824}
8925
90- // Reset will reset the container and remove all the bindings .
26+ // Reset removes all bindings in the default instance .
9127func Reset () {
92- container = map [reflect. Type ] binding {}
28+ container . Reset ()
9329}
9430
95- // Make will resolve the dependency and return a appropriate concrete of the given abstraction.
96- // It can take an abstraction (interface reference) and fill it with the related implementation.
97- // It also can takes a function (receiver) with one or more arguments of the abstractions (interfaces) that need to be
98- // resolved, Container will invoke the receiver function and pass the related implementations.
31+ // Make binds receiver to the default instance.
9932func Make (receiver interface {}) {
100- receiverTypeOf := reflect .TypeOf (receiver )
101- if receiverTypeOf == nil {
102- panic ("cannot detect type of the receiver, make sure your are passing reference of the object" )
103- }
104-
105- if receiverTypeOf .Kind () == reflect .Ptr {
106- abstraction := receiverTypeOf .Elem ()
107-
108- if concrete , ok := container [abstraction ]; ok {
109- instance := concrete .resolve ()
110- reflect .ValueOf (receiver ).Elem ().Set (reflect .ValueOf (instance ))
111- return
112- }
113-
114- panic ("no concrete found for the abstraction " + abstraction .String ())
115- }
116-
117- if receiverTypeOf .Kind () == reflect .Func {
118- arguments := arguments (receiver )
119- reflect .ValueOf (receiver ).Call (arguments )
120- return
121- }
122-
123- panic ("the receiver must be either a reference or a callback" )
124- }
33+ container .Make (receiver )
34+ }
0 commit comments