github.com/zly-app/zapp@v1.3.3/config/watch.reset_obj_callback.go (about)

     1  package config
     2  
     3  import (
     4  	"reflect"
     5  )
     6  
     7  func init() {
     8  	AddResetInjectStructuredHook(resetInjectObjCallback)
     9  }
    10  
    11  type ResetInjectStructuredHook func(injectObj interface{}, newData []byte) (result interface{}, resultData []byte, cancel bool)
    12  
    13  var resetInjectStructuredHooks []ResetInjectStructuredHook
    14  
    15  // 添加重设注入结构拦截
    16  func AddResetInjectStructuredHook(hooks ...ResetInjectStructuredHook) {
    17  	resetInjectStructuredHooks = append(resetInjectStructuredHooks, hooks...)
    18  }
    19  
    20  var resetInjectObjCallbacks = make(map[reflect.Type]func(injectObj interface{}, isField bool))
    21  
    22  /*
    23  添加重设结构注入结构回调, 只有注入结构是指针才有效
    24  
    25  如果注入结构实现了 T, 则会调用回调函数并传入注入结构的值, 其isField为false
    26  如果注入结构是一个struct, 则会遍历其导出字段(包括继承)判断实现了 T , 则会调用回调函数并传入其字段的值, 其isField为true.
    27  */
    28  func AddResetInjectObjCallback[T any](callback func(obj T, isField bool)) {
    29  	o := new(T)
    30  	rt := reflect.TypeOf(o).Elem()
    31  	resetInjectObjCallbacks[rt] = func(obj interface{}, isField bool) {
    32  		callback(obj.(T), isField)
    33  	}
    34  }
    35  
    36  func resetInjectObjCallback(injectObj interface{}, newData []byte) (result interface{}, resultData []byte, cancel bool) {
    37  	result = injectObj
    38  	resultData = newData
    39  	cancel = false
    40  
    41  	match := func(t reflect.Type, isField bool, get func() interface{}) {
    42  		for rt, callback := range resetInjectObjCallbacks {
    43  			if t.AssignableTo(rt) {
    44  				callback(get(), isField)
    45  			}
    46  		}
    47  	}
    48  
    49  	rv := reflect.ValueOf(injectObj)
    50  	if rv.Type().Kind() == reflect.Ptr {
    51  		match(rv.Type(), false, func() interface{} {
    52  			return rv.Interface()
    53  		})
    54  	}
    55  
    56  	rv = reflect.Indirect(rv)
    57  	rt := rv.Type()
    58  
    59  	if rv.Kind() == reflect.Struct {
    60  		num := rt.NumField()
    61  		for i := 0; i < num; i++ {
    62  			ft := rt.Field(i)
    63  			if ft.PkgPath != "" || ft.Type.Kind() != reflect.Ptr {
    64  				continue
    65  			}
    66  			match(ft.Type, true, func() interface{} {
    67  				return rv.Field(i).Interface()
    68  			})
    69  		}
    70  	}
    71  	return
    72  }