mirror of
https://github.com/kataras/iris.git
synced 2026-01-27 05:45:56 +00:00
Update to version 12.1.8 - Read HISTORY.md
Former-commit-id: d3d30cb15537146e3071731be9d674a5cb59de97
This commit is contained in:
113
hero/di/func.go
113
hero/di/func.go
@@ -18,10 +18,10 @@ type (
|
||||
FuncInjector struct {
|
||||
// the original function, is being used
|
||||
// only the .Call, which is referring to the same function, always.
|
||||
fn reflect.Value
|
||||
typ reflect.Type
|
||||
goodFunc TypeChecker
|
||||
errorHandler ErrorHandler
|
||||
fn reflect.Value
|
||||
typ reflect.Type
|
||||
FallbackBinder FallbackBinder
|
||||
ErrorHandler ErrorHandler
|
||||
|
||||
inputs []*targetFuncInput
|
||||
// Length is the number of the valid, final binded input arguments.
|
||||
@@ -51,13 +51,13 @@ func (s *FuncInjector) miss(index int, remaining Values) {
|
||||
// that the caller should use to bind input arguments of the "fn" function.
|
||||
//
|
||||
// The hijack and the goodFunc are optional, the "values" is the dependencies collection.
|
||||
func MakeFuncInjector(fn reflect.Value, hijack Hijacker, goodFunc TypeChecker, errorHandler ErrorHandler, values ...reflect.Value) *FuncInjector {
|
||||
func MakeFuncInjector(fn reflect.Value, values ...reflect.Value) *FuncInjector {
|
||||
typ := IndirectType(fn.Type())
|
||||
s := &FuncInjector{
|
||||
fn: fn,
|
||||
typ: typ,
|
||||
goodFunc: goodFunc,
|
||||
errorHandler: errorHandler,
|
||||
fn: fn,
|
||||
typ: typ,
|
||||
FallbackBinder: DefaultFallbackBinder,
|
||||
ErrorHandler: DefaultErrorHandler,
|
||||
}
|
||||
|
||||
if !IsFunc(typ) {
|
||||
@@ -71,16 +71,12 @@ func MakeFuncInjector(fn reflect.Value, hijack Hijacker, goodFunc TypeChecker, e
|
||||
for i := 0; i < n; i++ {
|
||||
inTyp := typ.In(i)
|
||||
|
||||
if hijack != nil {
|
||||
b, ok := hijack(inTyp)
|
||||
|
||||
if ok && b != nil {
|
||||
s.inputs = append(s.inputs, &targetFuncInput{
|
||||
InputIndex: i,
|
||||
Object: b,
|
||||
})
|
||||
continue
|
||||
}
|
||||
if b, ok := tryBindContext(inTyp); ok {
|
||||
s.inputs = append(s.inputs, &targetFuncInput{
|
||||
InputIndex: i,
|
||||
Object: b,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
matched := false
|
||||
@@ -98,6 +94,50 @@ func MakeFuncInjector(fn reflect.Value, hijack Hijacker, goodFunc TypeChecker, e
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
// TODO: (already working on it) clean up or even re-write the whole di, hero and some of the mvc,
|
||||
// this is a dirty but working-solution for #1449.
|
||||
// Limitations:
|
||||
// - last input argument
|
||||
// - not able to customize it other than DefaultFallbackBinder on MVC (on hero it can be customized)
|
||||
// - the "di" package is now depends on context package which is not an import-cycle issue, it's not imported there.
|
||||
if i == n-1 {
|
||||
if v.Type() == autoBindingTyp && s.FallbackBinder != nil {
|
||||
|
||||
canFallback := true
|
||||
if k := inTyp.Kind(); k == reflect.Ptr {
|
||||
if inTyp.Elem().Kind() != reflect.Struct {
|
||||
canFallback = false
|
||||
}
|
||||
} else if k != reflect.Struct {
|
||||
canFallback = false
|
||||
}
|
||||
|
||||
if canFallback {
|
||||
matched = true
|
||||
|
||||
s.inputs = append(s.inputs, &targetFuncInput{
|
||||
InputIndex: i,
|
||||
Object: &BindObject{
|
||||
Type: inTyp,
|
||||
BindType: Dynamic,
|
||||
ReturnValue: func(ctx context.Context) reflect.Value {
|
||||
value, err := s.FallbackBinder(ctx, OrphanInput{Type: inTyp})
|
||||
if err != nil {
|
||||
if s.ErrorHandler != nil {
|
||||
s.ErrorHandler.HandleError(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !matched {
|
||||
@@ -108,7 +148,6 @@ func MakeFuncInjector(fn reflect.Value, hijack Hijacker, goodFunc TypeChecker, e
|
||||
// with different set of binding "values".
|
||||
s.miss(i, values) // send the remaining dependencies values.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return s
|
||||
@@ -119,6 +158,11 @@ func (s *FuncInjector) refresh() {
|
||||
s.Has = s.Length > 0
|
||||
}
|
||||
|
||||
// AutoBindingValue a fake type to expliclty set the return value of hero.AutoBinding.
|
||||
type AutoBindingValue struct{}
|
||||
|
||||
var autoBindingTyp = reflect.TypeOf(AutoBindingValue{})
|
||||
|
||||
func (s *FuncInjector) addValue(inputIndex int, value reflect.Value) bool {
|
||||
defer s.refresh()
|
||||
|
||||
@@ -129,31 +173,14 @@ func (s *FuncInjector) addValue(inputIndex int, value reflect.Value) bool {
|
||||
inTyp := s.typ.In(inputIndex)
|
||||
|
||||
// the binded values to the func's inputs.
|
||||
b, err := MakeBindObject(value, s.goodFunc, s.errorHandler)
|
||||
b, err := MakeBindObject(value, s.ErrorHandler)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: expose that (need to push a fix for issue #1450 first)
|
||||
if b.Type == reflectValueType {
|
||||
b.Type = inTyp
|
||||
// returnValue := b.ReturnValue
|
||||
b.ReturnValue = func(ctx context.Context) reflect.Value {
|
||||
newValue := reflect.New(inTyp)
|
||||
|
||||
if err := ctx.ReadJSON(newValue.Interface()); err != nil {
|
||||
if s.errorHandler != nil {
|
||||
s.errorHandler.HandleError(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
return newValue.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
if b.IsAssignable(inTyp) {
|
||||
// fmt.Printf("binded input index: %d for type: %s and value: %v with pointer: %v\n",
|
||||
// i, b.Type.String(), inTyp.String(), inTyp.Pointer())
|
||||
// fmt.Printf("binded input index: %d for type: %s and value: %v with dependency: %v\n",
|
||||
// inputIndex, b.Type.String(), inTyp.String(), b)
|
||||
s.inputs = append(s.inputs, &targetFuncInput{
|
||||
InputIndex: inputIndex,
|
||||
Object: &b,
|
||||
@@ -164,12 +191,6 @@ func (s *FuncInjector) addValue(inputIndex int, value reflect.Value) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ErrorHandler registers an error handler for this FuncInjector.
|
||||
func (s *FuncInjector) ErrorHandler(errorHandler ErrorHandler) *FuncInjector {
|
||||
s.errorHandler = errorHandler
|
||||
return s
|
||||
}
|
||||
|
||||
// Retry used to add missing dependencies, i.e path parameter builtin bindings if not already exists
|
||||
// in the `hero.Handler`, once, only for that func injector.
|
||||
func (s *FuncInjector) Retry(retryFn func(inIndex int, inTyp reflect.Type, remainingValues Values) (reflect.Value, bool)) bool {
|
||||
|
||||
Reference in New Issue
Block a user