Files

122 lines
3.5 KiB
Go

package condflow
import (
"fmt"
"reflect"
"git.fsdpf.net/go/reflux"
"git.fsdpf.net/go/reflux/valuex"
"git.fsdpf.net/go/req"
)
// Action 条件分支处理函数
type Action func(ctx Context, cfg valuex.Accessor) (reflux.R, error)
// ActionInvoker 调用器接口,用于管理和调用 Action 方法
type ActionInvoker interface {
// Res 获取默认资源
Res() req.Resource
// GetActionResource 获取指定 action 的资源,如果未设置则返回默认资源
GetActionResource(actionName string) req.Resource
// GetAction 获取指定名称的 Action 函数
GetAction(name string) (Action, error)
// Call 调用指定名称的 Action 方法
Call(ctx FlowContext, name string, cfg valuex.Accessor) (reflux.R, error)
}
// actionInvoker ActionInvoker 的默认实现
type actionInvoker struct {
defRes req.Resource // 默认资源
actRes map[string]req.Resource // 每个 action 对应的资源
executorValue reflect.Value // 缓存 Executor 反射值
}
// NewActionInvoker 创建新的 ActionInvoker
func NewActionInvoker(e Executor, actRes map[string]req.Resource) ActionInvoker {
if actRes == nil {
actRes = make(map[string]req.Resource)
}
return &actionInvoker{
defRes: e.Res(),
actRes: actRes,
executorValue: reflect.ValueOf(e),
}
}
// NewActionInvokerWithValue 使用 reflect.Value 创建新的 ActionInvoker
func NewActionInvokerWithValue(executorValue reflect.Value, actRes map[string]req.Resource) ActionInvoker {
if actRes == nil {
actRes = make(map[string]req.Resource)
}
// 通过反射调用 Res() 方法获取默认资源
resMethod := executorValue.MethodByName("Res")
if !resMethod.IsValid() {
panic("executor must have Res() method")
}
results := resMethod.Call(nil)
defRes := results[0].Interface().(req.Resource)
return &actionInvoker{
defRes: defRes,
actRes: actRes,
executorValue: executorValue,
}
}
// Res 获取默认资源
func (ai *actionInvoker) Res() req.Resource {
return ai.defRes
}
// Call 调用指定名称的 Action 方法
func (ai *actionInvoker) Call(ctx FlowContext, name string, cfg valuex.Accessor) (reflux.R, error) {
action, err := ai.GetAction(name)
if err != nil {
return nil, err
}
return action(toActionContext(ctx, ai.GetActionResource(name)), cfg)
}
// GetActionResource 获取指定 action 的资源,如果未设置则返回默认资源
func (ai *actionInvoker) GetActionResource(actionName string) req.Resource {
if res, exists := ai.actRes[actionName]; exists {
return res
}
return ai.defRes
}
// GetAction 通过反射获取 Executor 中指定名称的 Action 方法
// - name: 方法名称,如 "AutoApproveAction"
func (ai *actionInvoker) GetAction(name string) (Action, error) {
// 使用缓存的 executorValue
method := ai.executorValue.MethodByName(name)
if !method.IsValid() {
return nil, fmt.Errorf("action method '%s' not found in '%s", name, ai.executorValue.Type().String())
}
// 获取方法类型信息
methodType := method.Type()
// 验证方法签名: func(Context, valuex.Accessor) (reflux.R, error)
// NumIn: 2 个参数 (不包括接收者)
// NumOut: 2 个返回值
if methodType.NumIn() != 2 || methodType.NumOut() != 2 {
return nil, fmt.Errorf("action method '%s' has invalid signature, expected func(Context, valuex.Accessor) (reflux.R, error)", name)
}
// 转换为 Action 类型
action, ok := method.Interface().(func(ctx Context, cfg valuex.Accessor) (reflux.R, error))
if !ok {
return nil, fmt.Errorf("failed to convert method '%s' to Action type", name)
}
return action, nil
}