github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zdi/bind.go (about)

     1  package zdi
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  
     8  	"github.com/sohaha/zlsgo/zreflect"
     9  )
    10  
    11  func (inj *injector) Resolve(v ...Pointer) error {
    12  	for _, p := range v {
    13  		r := zreflect.ValueOf(p)
    14  		rt := r.Type()
    15  		v := r
    16  		t := rt
    17  		for v.Kind() == reflect.Ptr {
    18  			v = v.Elem()
    19  			t = rt.Elem()
    20  		}
    21  
    22  		if !v.IsValid() {
    23  			var val reflect.Value
    24  			var ok bool
    25  
    26  			val, ok = inj.Get(t)
    27  			if !ok {
    28  				return errors.New("can't find injector for " + t.String())
    29  			}
    30  
    31  			if !v.IsValid() && r.IsValid() {
    32  				if t.Kind() == reflect.Ptr {
    33  					r.Elem().Set(val)
    34  					continue
    35  				}
    36  			}
    37  
    38  			return errors.New("invalid pointer")
    39  		}
    40  
    41  		if !v.CanSet() {
    42  			return errors.New("cannot set value")
    43  		}
    44  
    45  		typ := v.Type()
    46  		val, ok := inj.Get(typ)
    47  		if !ok {
    48  			return errors.New("can't find injector for " + t.String())
    49  		}
    50  
    51  		v.Set(val)
    52  	}
    53  	return nil
    54  }
    55  
    56  func (inj *injector) Apply(p Pointer) error {
    57  	v := zreflect.ValueOf(p)
    58  	for v.Kind() == reflect.Ptr {
    59  		v = v.Elem()
    60  	}
    61  
    62  	if !v.CanSet() {
    63  		return errors.New("cannot set value")
    64  	}
    65  
    66  	typ := v.Type()
    67  	val, ok := inj.Get(typ)
    68  	if ok {
    69  		v.Set(val)
    70  		return nil
    71  	}
    72  
    73  	if v.Kind() != reflect.Struct {
    74  		val, ok := inj.Get(typ)
    75  		if !ok {
    76  			return nil
    77  		}
    78  		v.Set(val)
    79  		return nil
    80  	}
    81  
    82  	for i := 0; i < v.NumField(); i++ {
    83  		f := v.Field(i)
    84  		structField := typ.Field(i)
    85  		_, ok := structField.Tag.Lookup("di")
    86  		if f.CanSet() && ok {
    87  			ft := f.Type()
    88  			v, ok := inj.Get(ft)
    89  			if !ok {
    90  				return fmt.Errorf("value not found for type %v", ft)
    91  			}
    92  			f.Set(v)
    93  		}
    94  	}
    95  	return nil
    96  }