iris/mvc2/binder_in_service.go
kataras a7b2a90e3b cm
Former-commit-id: 8f99121b81dc76c04d5910117885d9286873f26c
2017-12-04 05:08:05 +02:00

82 lines
1.8 KiB
Go

package mvc2
import (
"reflect"
)
type serviceFieldBinder struct {
Index []int
Binder *InputBinder
}
func getServicesBinderForStruct(binders []*InputBinder, typ reflect.Type) func(elem reflect.Value) {
fields := lookupFields(typ, -1)
var validBinders []*serviceFieldBinder
for _, b := range binders {
for _, f := range fields {
if b.BinderType != serviceType {
continue
}
if equalTypes(b.BindType, f.Type) {
validBinders = append(validBinders,
&serviceFieldBinder{Index: f.Index, Binder: b})
}
}
}
if len(validBinders) == 0 {
return func(_ reflect.Value) {}
}
return func(elem reflect.Value) {
for _, b := range validBinders {
elem.FieldByIndex(b.Index).Set(b.Binder.BindFunc(nil))
}
}
}
// MustMakeServiceInputBinder calls the `MakeServiceInputBinder` and returns its first result, see its docs.
// It panics on error.
func MustMakeServiceInputBinder(service interface{}) *InputBinder {
s, err := MakeServiceInputBinder(service)
if err != nil {
panic(err)
}
return s
}
// MakeServiceInputBinder uses a difference/or strange approach,
// we make the services as bind functions
// in order to keep the rest of the code simpler, however we have
// a performance penalty when calling the function instead
// of just put the responsible service to the certain handler's input argument.
func MakeServiceInputBinder(service interface{}) (*InputBinder, error) {
if service == nil {
return nil, errNil
}
var (
val = reflect.ValueOf(service)
typ = val.Type()
)
if !goodVal(val) {
return nil, errBad
}
if indirectTyp(typ).Kind() != reflect.Struct {
// if the pointer's struct is not a struct then return err bad.
return nil, errBad
}
return &InputBinder{
BinderType: serviceType,
BindType: typ,
BindFunc: func(_ []reflect.Value) reflect.Value {
return val
},
}, nil
}