mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 16:55:15 +00:00
bbgo: implement parseStructAndInject
This commit is contained in:
parent
5fe0b69927
commit
db4d8a31bc
|
@ -413,3 +413,57 @@ func (trader *Trader) injectCommonServices(rs reflect.Value) error {
|
|||
func (trader *Trader) ReportPnL() *PnLReporterManager {
|
||||
return NewPnLReporter(&trader.environment.Notifiability)
|
||||
}
|
||||
|
||||
func parseStructAndInject(f interface{}, objects ...interface{}) error {
|
||||
sv := reflect.ValueOf(f)
|
||||
st := reflect.TypeOf(f)
|
||||
|
||||
if st.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("f needs to be a pointer of a struct, %s given", st)
|
||||
}
|
||||
|
||||
// solve the pointer
|
||||
st = st.Elem()
|
||||
sv = sv.Elem()
|
||||
|
||||
if st.Kind() != reflect.Struct {
|
||||
return fmt.Errorf("f needs to be a struct, %s given", st)
|
||||
}
|
||||
|
||||
for i := 0; i < sv.NumField(); i++ {
|
||||
fv := sv.Field(i)
|
||||
ft := fv.Type()
|
||||
|
||||
switch k := fv.Kind(); k {
|
||||
|
||||
case reflect.Ptr, reflect.Struct:
|
||||
for oi := 0; oi < len(objects); oi++ {
|
||||
obj := objects[oi]
|
||||
ot := reflect.TypeOf(obj)
|
||||
if ft.AssignableTo(ot) {
|
||||
if !fv.CanSet() {
|
||||
return fmt.Errorf("field %v of %s can not be set to %s", fv, sv.Type(), ot)
|
||||
}
|
||||
fv.Set(reflect.ValueOf(obj))
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Interface:
|
||||
for oi := 0; oi < len(objects); oi++ {
|
||||
obj := objects[oi]
|
||||
objT := reflect.TypeOf(obj)
|
||||
log.Debugln(
|
||||
ft.PkgPath(),
|
||||
ft.Name(),
|
||||
objT, "implements", ft, "=", objT.Implements(ft),
|
||||
)
|
||||
|
||||
if objT.Implements(ft) {
|
||||
fv.Set(reflect.ValueOf(obj))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
60
pkg/bbgo/trader_test.go
Normal file
60
pkg/bbgo/trader_test.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package bbgo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
func Test_parseStructAndInject(t *testing.T) {
|
||||
t.Run("pointer", func(t *testing.T) {
|
||||
ss := struct {
|
||||
a int
|
||||
Env *Environment
|
||||
}{
|
||||
a: 1,
|
||||
Env: nil,
|
||||
}
|
||||
err := parseStructAndInject(&ss, &Environment{})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, ss.Env)
|
||||
})
|
||||
t.Run("struct", func(t *testing.T) {
|
||||
ss := struct {
|
||||
a int
|
||||
Env Environment
|
||||
}{
|
||||
a: 1,
|
||||
}
|
||||
err := parseStructAndInject(&ss, Environment{
|
||||
startTime: time.Now(),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotEqual(t, time.Time{}, ss.Env.startTime)
|
||||
})
|
||||
t.Run("interface/any", func(t *testing.T) {
|
||||
ss := struct {
|
||||
Any interface{} // anything
|
||||
}{
|
||||
Any: nil,
|
||||
}
|
||||
err := parseStructAndInject(&ss, &Environment{
|
||||
startTime: time.Now(),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, ss.Any)
|
||||
})
|
||||
t.Run("interface/stringer", func(t *testing.T) {
|
||||
ss := struct {
|
||||
Stringer types.Stringer // stringer interface
|
||||
}{
|
||||
Stringer: nil,
|
||||
}
|
||||
err := parseStructAndInject(&ss, &types.Trade{})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, ss.Stringer)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user