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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
type Container struct { providers map[reflect.Type]provider
results map[reflect.Type]reflect.Value }
type provider struct { value reflect.Value params []reflect.Type }
func New() *Container { return &Container{ providers: map[reflect.Type]provider{}, results: map[reflect.Type]reflect.Value{}, } }
func isError(t reflect.Type) bool { if t.Kind() != reflect.Interface { return false } return t.Implements(reflect.TypeOf(reflect.TypeOf((*error)(nil)).Elem())) }
func (c *Container) Provide(constructor interface{}) error { v := reflect.ValueOf(constructor)
if v.Kind() != reflect.Func { return fmt.Errorf("constructor must be a func") }
vt := v.Type()
params := make([]reflect.Type, vt.NumIn()) for i := 0; i < vt.NumIn(); i++ { params[i] = vt.In(i) }
results := make([]reflect.Type, vt.NumOut()) for i := 0; i < vt.NumOut(); i++ { results[i] = vt.Out(i) }
provider := provider{ value: v, params: params}
for _, result := range results { if isError(result) { continue } if _, ok := c.providers[result]; ok { return fmt.Errorf("%s had a provider", result) } c.providers[result] = provider } return nil }
func (c *Container) Invoke(function interface{}) error { v := reflect.ValueOf(function) if v.Kind() != reflect.Func { return fmt.Errorf("constructor must be a func") }
vt := v.Type()
var err error params:= make([]reflect.Value,vt.NumIn()) for i:=0;i<vt.NumIn();i++{ params[i], err = c.buildParam(vt.In(i)) if err != nil { return err } } v.Call(params)
return nil }
func (c *Container) buildParam(param reflect.Type)(val reflect.Value, err error){ if result, ok := c.results[param]; ok { return result, nil } provider, ok := c.providers[param] if !ok { return reflect.Value{}, fmt.Errorf("can not found provider: %s", param) } params := make([]reflect.Value, len(provider.params)) for i, p := range provider.params { params[i], err = c.buildParam(p) } results := provider.value.Call(params) for _, result := range results { if isError(result.Type()) && !result.IsNil() { return reflect.Value{}, fmt.Errorf("%s call err: %+v", provider, result) } if !isError(result.Type()) && !result.IsNil() { c.results[result.Type()] = result } } return c.results[param], nil }
|