|
| 1 | +package wool |
| 2 | + |
| 3 | +import ( |
| 4 | + "errors" |
| 5 | + "reflect" |
| 6 | +) |
| 7 | + |
| 8 | +// not export , so others can't implement the package |
| 9 | +type dic struct { |
| 10 | + container map[reflect.Type]*__obj |
| 11 | +} |
| 12 | + |
| 13 | +type DIC interface { |
| 14 | + Bind(it interface{}, v interface{}) error |
| 15 | + BindSingleton(it interface{}, v interface{}) error |
| 16 | + Make(it interface{}, args ...interface{}) error |
| 17 | +} |
| 18 | + |
| 19 | +var di *dic |
| 20 | + |
| 21 | +type __obj struct { |
| 22 | + instance interface{} |
| 23 | + __type reflect.Type |
| 24 | + __value reflect.Value |
| 25 | + singleton bool |
| 26 | +} |
| 27 | + |
| 28 | +// DI singleton |
| 29 | +func DI() DIC { |
| 30 | + if di == nil { |
| 31 | + di = &dic{ |
| 32 | + container: make(map[reflect.Type]*__obj), |
| 33 | + } |
| 34 | + } |
| 35 | + return di |
| 36 | +} |
| 37 | + |
| 38 | +func (di *dic) Bind(it interface{}, v interface{}) error { |
| 39 | + return di.bind(it, v, false) |
| 40 | +} |
| 41 | + |
| 42 | +func (di *dic) BindSingleton(it interface{}, v interface{}) error { |
| 43 | + return di.bind(it, v, true) |
| 44 | +} |
| 45 | + |
| 46 | +// Bind it's type must be no-empty reflect.Interface |
| 47 | +// c's type can be reflect.Func or reflect.Struct |
| 48 | +func (di *dic) bind(it interface{}, v interface{}, singleton bool) error { |
| 49 | + itType := reflect.TypeOf(it) |
| 50 | + vType := reflect.TypeOf(v) |
| 51 | + if itType.Kind() != reflect.Ptr { |
| 52 | + return errors.New("it is not ptr") |
| 53 | + } |
| 54 | + // just check |
| 55 | + switch vType.Kind() { |
| 56 | + case reflect.Func: |
| 57 | + if vType.In(0) != reflect.TypeOf(di) { |
| 58 | + return errors.New("first params must be DIC") |
| 59 | + } |
| 60 | + if vType.Out(0) != itType { |
| 61 | + return errors.New("first return params must same as it's type") |
| 62 | + } |
| 63 | + default: |
| 64 | + } |
| 65 | + obj := &__obj{ |
| 66 | + __type: vType, |
| 67 | + __value: reflect.ValueOf(v), |
| 68 | + } |
| 69 | + di.set(itType, obj) |
| 70 | + return nil |
| 71 | +} |
| 72 | + |
| 73 | +// Make it must be reflect.Ptr |
| 74 | +// it's point obj must be reflect.Struct or reflect.Interface |
| 75 | +func (di *dic) Make(it interface{}, args ...interface{}) error { |
| 76 | + itType := reflect.TypeOf(it) |
| 77 | + obj, ok := di.load(itType) |
| 78 | + if itType.Kind() != reflect.Ptr || !ok { |
| 79 | + return errors.New("can't find interface") |
| 80 | + } |
| 81 | + switch obj.__type.Kind() { |
| 82 | + case reflect.Func: |
| 83 | + var argValues = make([]reflect.Value, 0) |
| 84 | + for _, arg := range args { |
| 85 | + argValues = append(argValues, reflect.ValueOf(arg)) |
| 86 | + } |
| 87 | + // todo error handle |
| 88 | + buildValue := obj.__value.Call(argValues) |
| 89 | + reflect.ValueOf(it).Elem().Set(buildValue[0]) |
| 90 | + default: |
| 91 | + reflect.ValueOf(it).Elem().Set(obj.__value) |
| 92 | + return nil |
| 93 | + } |
| 94 | + return nil |
| 95 | +} |
| 96 | + |
| 97 | +// todo lock |
| 98 | +func (di *dic) set(it reflect.Type, c *__obj) { |
| 99 | + di.container[it] = c |
| 100 | +} |
| 101 | + |
| 102 | +func (di *dic) load(it reflect.Type) (obj *__obj, exist bool) { |
| 103 | + obj, exist = di.container[it] |
| 104 | + return |
| 105 | +} |
0 commit comments