-
Notifications
You must be signed in to change notification settings - Fork 1
/
injector.go
65 lines (54 loc) · 1.33 KB
/
injector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package attache
import (
"log"
"net/http"
"reflect"
)
type injector struct {
app *Application
ctx Context
req *http.Request
res http.ResponseWriter
provided []reflect.Value
}
var (
tRequest = reflect.TypeOf((*http.Request)(nil))
tResponseWriter = reflect.TypeOf((*http.ResponseWriter)(nil)).Elem()
tContext = reflect.TypeOf((*Context)(nil)).Elem()
)
func (i injector) getFor(typ reflect.Type) reflect.Value {
// special cases
switch true {
// provide *http.Request
case typ == tRequest:
return reflect.ValueOf(i.req)
// provide http.ResponseWriter
case typ == tResponseWriter:
return reflect.ValueOf(i.res)
// provide concrete Context where applicable
case i.app.contextType.AssignableTo(typ):
return reflect.ValueOf(i.ctx)
// try lookup or default to the zero value
default:
for _, x := range i.provided {
xtyp := x.Type()
if xtyp.AssignableTo(typ) {
return x
}
if x.CanAddr() && reflect.PtrTo(xtyp).AssignableTo(typ) {
return x.Addr()
}
}
log.Printf("inject: unrecognized type %s, using zero value", typ)
return reflect.Zero(typ)
}
}
func (i *injector) apply(fn reflect.Value) {
typ := fn.Type()
args := make([]reflect.Value, typ.NumIn())
for x := 0; x < typ.NumIn(); x++ {
args[x] = i.getFor(typ.In(x))
}
// for now, ignore results
_ = fn.Call(args)
}