mirror of
https://github.com/kataras/iris.git
synced 2026-01-07 12:07:28 +00:00
cm
Former-commit-id: 8f99121b81dc76c04d5910117885d9286873f26c
This commit is contained in:
4
mvc2/binder/binder/input.go
Normal file
4
mvc2/binder/binder/input.go
Normal file
@@ -0,0 +1,4 @@
|
||||
package binder
|
||||
|
||||
type Input interface {
|
||||
}
|
||||
19
mvc2/binder/binding.go
Normal file
19
mvc2/binder/binding.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package binder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Binding interface {
|
||||
AddSource(v reflect.Value, source ...reflect.Value)
|
||||
}
|
||||
|
||||
type StructValue struct {
|
||||
Type reflect.Type
|
||||
Value reflect.Value
|
||||
}
|
||||
|
||||
type FuncResultValue struct {
|
||||
Type reflect.Type
|
||||
ReturnValue func(ctx []reflect.Value) reflect.Value
|
||||
}
|
||||
1
mvc2/binder/func_input.go
Normal file
1
mvc2/binder/func_input.go
Normal file
@@ -0,0 +1 @@
|
||||
package binder
|
||||
53
mvc2/binder/func_result.go
Normal file
53
mvc2/binder/func_result.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package binder
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
errBad = errors.New("bad")
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
107
mvc2/binder/reflect.go
Normal file
107
mvc2/binder/reflect.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package binder
|
||||
|
||||
import "reflect"
|
||||
|
||||
func isContext(inTyp reflect.Type) bool {
|
||||
return inTyp.String() == "context.Context" // I couldn't find another way; context/context.go is not exported.
|
||||
}
|
||||
|
||||
func indirectVal(v reflect.Value) reflect.Value {
|
||||
return reflect.Indirect(v)
|
||||
}
|
||||
|
||||
func indirectTyp(typ reflect.Type) reflect.Type {
|
||||
switch typ.Kind() {
|
||||
case reflect.Ptr, reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
|
||||
return typ.Elem()
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
func goodVal(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
|
||||
if v.IsNil() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return v.IsValid()
|
||||
}
|
||||
|
||||
func isFunc(typ reflect.Type) bool {
|
||||
return typ.Kind() == reflect.Func
|
||||
}
|
||||
|
||||
/*
|
||||
// no f. this, it's too complicated and it will be harder to maintain later on:
|
||||
func isSliceAndExpectedItem(got reflect.Type, in []reflect.Type, currentBindersIdx int) bool {
|
||||
kind := got.Kind()
|
||||
// if got result is slice or array.
|
||||
return (kind == reflect.Slice || kind == reflect.Array) &&
|
||||
// if has expected next input.
|
||||
len(in)-1 > currentBindersIdx &&
|
||||
// if the current input's type is not the same as got (if it's not a slice of that types or anything else).
|
||||
equalTypes(got, in[currentBindersIdx])
|
||||
}
|
||||
*/
|
||||
|
||||
func equalTypes(got reflect.Type, expected reflect.Type) bool {
|
||||
if got == expected {
|
||||
return true
|
||||
}
|
||||
// if accepts an interface, check if the given "got" type does
|
||||
// implement this "expected" user handler's input argument.
|
||||
if expected.Kind() == reflect.Interface {
|
||||
// fmt.Printf("expected interface = %s and got to set on the arg is: %s\n", expected.String(), got.String())
|
||||
return got.Implements(expected)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// for controller only.
|
||||
|
||||
func structFieldIgnored(f reflect.StructField) bool {
|
||||
if !f.Anonymous {
|
||||
return true // if not anonymous(embedded), ignore it.
|
||||
}
|
||||
|
||||
s := f.Tag.Get("ignore")
|
||||
return s == "true" // if has an ignore tag then ignore it.
|
||||
}
|
||||
|
||||
type field struct {
|
||||
Type reflect.Type
|
||||
Index []int // the index of the field, slice if it's part of a embedded struct
|
||||
Name string // the actual name
|
||||
|
||||
// this could be empty, but in our cases it's not,
|
||||
// it's filled with the service and it's filled from the lookupFields' caller.
|
||||
AnyValue reflect.Value
|
||||
}
|
||||
|
||||
func lookupFields(typ reflect.Type, parentIndex int) (fields []field) {
|
||||
for i, n := 0, typ.NumField(); i < n; i++ {
|
||||
f := typ.Field(i)
|
||||
|
||||
if f.Type.Kind() == reflect.Struct && !structFieldIgnored(f) {
|
||||
fields = append(fields, lookupFields(f.Type, i)...)
|
||||
continue
|
||||
}
|
||||
|
||||
index := []int{i}
|
||||
if parentIndex >= 0 {
|
||||
index = append([]int{parentIndex}, index...)
|
||||
}
|
||||
|
||||
field := field{
|
||||
Type: f.Type,
|
||||
Name: f.Name,
|
||||
Index: index,
|
||||
}
|
||||
|
||||
fields = append(fields, field)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
50
mvc2/binder/to_struct.go
Normal file
50
mvc2/binder/to_struct.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package binder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type StructBinding struct {
|
||||
Field StructValue
|
||||
Func FuncResultValue
|
||||
}
|
||||
|
||||
func (b *StructBinding) AddSource(dest reflect.Value, source ...reflect.Value) {
|
||||
typ := indirectTyp(dest.Type()) //indirectTyp(reflect.TypeOf(dest))
|
||||
if typ.Kind() != reflect.Struct {
|
||||
return
|
||||
}
|
||||
|
||||
fields := lookupFields(typ, -1)
|
||||
for _, f := range fields {
|
||||
for _, s := range source {
|
||||
if s.Type().Kind() == reflect.Func {
|
||||
returnValue, outType, err := makeReturnValue(s)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
gotTyp = outType
|
||||
service.ReturnValue = returnValue
|
||||
}
|
||||
|
||||
gotTyp := s.Type()
|
||||
|
||||
v := StructValue{
|
||||
Type: gotTyp,
|
||||
Value: s,
|
||||
FieldIndex: f.Index,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user