122 lines
3.5 KiB
Go
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
|
|
}
|