mirror of
https://github.com/kataras/iris.git
synced 2025-01-24 03:01:03 +01:00
7043f352d9
Former-commit-id: e61c4573543c57b8d6d4ef2583e40f52c391402f
207 lines
4.4 KiB
Go
207 lines
4.4 KiB
Go
package mvc2
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
type service struct {
|
|
Type reflect.Type
|
|
Value reflect.Value
|
|
StructFieldIndex []int
|
|
|
|
// for func input.
|
|
ReturnValue func(ctx []reflect.Value) reflect.Value
|
|
FuncInputIndex int
|
|
FuncInputContextIndex int
|
|
}
|
|
|
|
type services []*service
|
|
|
|
func (serv *services) AddSource(dest reflect.Value, source ...reflect.Value) {
|
|
fmt.Println("--------------AddSource------------")
|
|
if len(source) == 0 {
|
|
return
|
|
}
|
|
|
|
typ := indirectTyp(dest.Type()) //indirectTyp(reflect.TypeOf(dest))
|
|
_serv := *serv
|
|
|
|
if typ.Kind() == reflect.Func {
|
|
n := typ.NumIn()
|
|
for i := 0; i < n; i++ {
|
|
|
|
inTyp := typ.In(i)
|
|
if isContext(inTyp) {
|
|
_serv = append(_serv, &service{FuncInputContextIndex: i})
|
|
continue
|
|
}
|
|
|
|
for _, s := range source {
|
|
gotTyp := s.Type()
|
|
|
|
service := service{
|
|
Type: gotTyp,
|
|
Value: s,
|
|
FuncInputIndex: i,
|
|
FuncInputContextIndex: -1,
|
|
}
|
|
|
|
if s.Type().Kind() == reflect.Func {
|
|
fmt.Printf("Source is Func\n")
|
|
returnValue, outType, err := makeReturnValue(s)
|
|
if err != nil {
|
|
fmt.Printf("Err on makeReturnValue: %v\n", err)
|
|
continue
|
|
}
|
|
gotTyp = outType
|
|
service.ReturnValue = returnValue
|
|
}
|
|
|
|
fmt.Printf("Types: In=%s vs Got=%s\n", inTyp.String(), gotTyp.String())
|
|
if equalTypes(gotTyp, inTyp) {
|
|
service.Type = gotTyp
|
|
fmt.Printf("Bind In=%s->%s for func\n", inTyp.String(), gotTyp.String())
|
|
_serv = append(_serv, &service)
|
|
|
|
break
|
|
}
|
|
}
|
|
}
|
|
fmt.Printf("[1] Bind %d for %s\n", len(_serv), typ.String())
|
|
*serv = _serv
|
|
|
|
return
|
|
}
|
|
|
|
if typ.Kind() == reflect.Struct {
|
|
fields := lookupFields(typ, -1)
|
|
for _, f := range fields {
|
|
for _, s := range source {
|
|
gotTyp := s.Type()
|
|
|
|
service := service{
|
|
Type: gotTyp,
|
|
Value: s,
|
|
StructFieldIndex: f.Index,
|
|
FuncInputContextIndex: -1,
|
|
}
|
|
|
|
if s.Type().Kind() == reflect.Func {
|
|
returnValue, outType, err := makeReturnValue(s)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
gotTyp = outType
|
|
service.ReturnValue = returnValue
|
|
}
|
|
|
|
if equalTypes(gotTyp, f.Type) {
|
|
service.Type = gotTyp
|
|
_serv = append(_serv, &service)
|
|
fmt.Printf("[2] Bind In=%s->%s for struct field[%d]\n", f.Type, gotTyp.String(), f.Index)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
fmt.Printf("[2] Bind %d for %s\n", len(_serv), typ.String())
|
|
*serv = _serv
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
func (serv services) FillStructStaticValues(elem reflect.Value) {
|
|
if len(serv) == 0 {
|
|
return
|
|
}
|
|
|
|
for _, s := range serv {
|
|
if len(s.StructFieldIndex) > 0 {
|
|
// fmt.Printf("FillStructStaticValues for index: %d\n", s.StructFieldIndex)
|
|
elem.FieldByIndex(s.StructFieldIndex).Set(s.Value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (serv services) FillStructDynamicValues(elem reflect.Value, ctx []reflect.Value) {
|
|
if len(serv) == 0 {
|
|
return
|
|
}
|
|
|
|
for _, s := range serv {
|
|
if len(s.StructFieldIndex) > 0 {
|
|
elem.FieldByIndex(s.StructFieldIndex).Set(s.ReturnValue(ctx))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (serv services) FillFuncInput(ctx []reflect.Value, destIn *[]reflect.Value) {
|
|
if len(serv) == 0 {
|
|
return
|
|
}
|
|
|
|
in := *destIn
|
|
for _, s := range serv {
|
|
if s.ReturnValue != nil {
|
|
in[s.FuncInputIndex] = s.ReturnValue(ctx)
|
|
continue
|
|
}
|
|
|
|
in[s.FuncInputIndex] = s.Value
|
|
if s.FuncInputContextIndex >= 0 {
|
|
in[s.FuncInputContextIndex] = ctx[0]
|
|
}
|
|
}
|
|
|
|
*destIn = in
|
|
}
|
|
|
|
func makeReturnValue(fn reflect.Value) (func([]reflect.Value) reflect.Value, reflect.Type, error) {
|
|
typ := indirectTyp(fn.Type())
|
|
|
|
// invalid if not a func.
|
|
if typ.Kind() != reflect.Func {
|
|
return nil, typ, errBad
|
|
}
|
|
|
|
// invalid if not returns one single value.
|
|
if typ.NumOut() != 1 {
|
|
return nil, typ, errBad
|
|
}
|
|
|
|
// invalid if input args length is not one.
|
|
if typ.NumIn() != 1 {
|
|
return nil, typ, errBad
|
|
}
|
|
|
|
// invalid if that single input arg is not a typeof context.Context.
|
|
if !isContext(typ.In(0)) {
|
|
return nil, typ, errBad
|
|
}
|
|
|
|
outTyp := typ.Out(0)
|
|
zeroOutVal := reflect.New(outTyp).Elem()
|
|
|
|
bf := func(ctxValue []reflect.Value) reflect.Value {
|
|
// []reflect.Value{reflect.ValueOf(ctx)}
|
|
results := fn.Call(ctxValue) // ctxValue is like that because of; read makeHandler.
|
|
if len(results) == 0 {
|
|
return zeroOutVal
|
|
}
|
|
|
|
v := results[0]
|
|
if !v.IsValid() {
|
|
return zeroOutVal
|
|
}
|
|
return v
|
|
}
|
|
|
|
return bf, outTyp, nil
|
|
}
|
|
|
|
func getServicesFor(dest reflect.Value, source []reflect.Value) (s services) {
|
|
s.AddSource(dest, source...)
|
|
return s
|
|
}
|