跳到主要内容
版本:Next

ActionActivity

分类: 通用步骤
命名空间: CMS.Plugin.FlowManagement.Abstractions.FlowBusiness.Activitys
基类: BusinessActivity
模块: FlowManagement.Abstractions

概述

ActionActivity 是动作节点的抽象基类,继承自 BusinessActivity。它提供了在流程节点生命周期的不同时机执行动作的能力,允许开发者精确控制动作的执行时机(进入前、进入时、执行时、退出前、退出时)。

所有需要在特定时机执行外部动作的节点(如 API 调用、脚本执行、方法调用等)都应该继承自 ActionActivity。

业务场景

适用场景

  • API 调用: 在特定时机调用外部 API
  • 脚本执行: 在流程的不同阶段执行脚本
  • 方法调用: 调用自定义的 C# 方法
  • 外部系统集成: 与外部系统进行交互
  • 事件触发: 在特定时机触发外部事件

在系统中的作用

ActionActivity 作为动作节点的基类,提供了:

  • 时机控制: 通过 Action 属性控制动作的执行时机
  • 同步/异步: 支持同步和异步执行模式
  • 异常处理: 统一的异常处理机制
  • 执行控制: 可以通过返回值控制流程是否继续

与其他节点的协作

  • BusinessActivity: 继承自 BusinessActivity,拥有所有基础功能
  • ApiCallActivity: 继承自 ActionActivity,用于 API 调用
  • MethodCallActivity: 继承自 ActionActivity,用于方法调用
  • ScriptCallActivity: 继承自 ActionActivity,用于脚本执行

配置说明

基本配置

属性名类型必填默认值说明
ActionActivityActionExecute执行的时机
IsSynchronousbooltrue是否同步处理

注:ActionActivity 继承了 BusinessActivity 的所有配置属性

配置项详解

Action

说明: 控制动作在节点生命周期中的执行时机。

取值范围: ActivityAction 枚举值

  • QueryEnter: 在 CanEnterAsync 时执行,可以阻止节点进入
  • Enter: 在 EnterAsync 时执行
  • Execute: 在 ProcessAsync 时执行(默认)
  • QueryExit: 在 CanExitAsync 时执行,可以阻止节点退出
  • Exit: 在 ExitAsync 时执行

注意事项:

  • QueryEnterQueryExit 可以通过返回 true 来阻止流程继续
  • Execute 是最常用的执行时机
  • 选择合适的时机可以实现更精确的流程控制

IsSynchronous

说明: 控制动作是同步执行还是异步执行。

取值范围: true 或 false

注意事项:

  • true: 同步执行,等待动作完成后继续
  • false: 异步执行,不等待动作完成,立即继续
  • 同步执行会捕获异常并可能阻止流程继续
  • 异步执行不会阻塞流程,但异常处理有限

流程上下文

ActionActivity 本身不定义特定的流程上下文键,由子类根据具体功能定义。

输入参数

由子类定义

输出参数

由子类定义

业务逻辑说明

处理流程

ActionActivity 根据 Action 属性在不同的生命周期阶段执行动作:

CanEnterAsync (Action=QueryEnter)

EnterAsync (Action=Enter)

ProcessAsync (Action=Execute)

CanExitAsync (Action=QueryExit)

ExitAsync (Action=Exit)

执行时机详解

  1. QueryEnter (进入前查询)

    • 在 CanEnterAsync 中执行
    • 如果返回 true,阻止节点进入
    • 用于进入前的条件检查
  2. Enter (进入时)

    • 在 EnterAsync 中执行
    • 节点进入时执行动作
    • 用于初始化操作
  3. Execute (执行时)

    • 在 ProcessAsync 中执行
    • 最常用的执行时机
    • 用于主要的业务逻辑
  4. QueryExit (退出前查询)

    • 在 CanExitAsync 中执行
    • 如果返回 true,阻止节点退出
    • 用于退出前的条件检查
  5. Exit (退出时)

    • 在 ExitAsync 中执行
    • 节点退出时执行动作
    • 用于清理操作

同步与异步执行

同步执行 (IsSynchronous = true):

try
{
await ExecuteActionAsync(args);
}
catch (Exception ex)
{
cancel = true;
Flow.Logger.LogExceptionMessage(ex);
}

异步执行 (IsSynchronous = false):

_ = ExecuteActionAsync(args).ContinueWith(task =>
{
if (!task.IsCompletedSuccessfully && task.Exception != null)
{
cancel = true;
Flow.Logger.LogExceptionMessage(task.Exception);
}
});

异常处理

  • 同步执行时,异常会被捕获并记录日志
  • 异常会导致 cancel 标志设置为 true
  • 在 QueryEnter 和 QueryExit 时,cancel=true 会阻止流程继续
  • 异步执行时,异常处理在后台进行

使用示例

基本示例 - 自定义动作节点

[Serializable]
[Design("自定义动作", "自定义动作节点示例", Sort = 1)]
[Category("自定义")]
public class CustomActionActivity : ActionActivity
{
[Design("动作参数", "动作参数说明", Sort = 1)]
[Category("配置")]
[DataMember]
public string ActionParameter { get; set; }

protected override async Task ExecuteActionAsync(ProcessflowEventArgs args)
{
// 实现具体的动作逻辑
Flow.Logger.LogMessage($"执行动作: {ActionParameter}", Name);

// 调用外部服务
var service = Flow.ServiceProvider.GetRequiredService<IMyService>();
await service.DoSomethingAsync(ActionParameter);

// 写入结果到流程上下文
Flow.DataItems["ActionResult"] = "Success";
}
}

高级示例 - 进入前检查

[Serializable]
[Design("条件检查动作", "在进入前检查条件", Sort = 2)]
[Category("自定义")]
public class ConditionalActionActivity : ActionActivity
{
public ConditionalActionActivity()
{
// 设置在进入前执行
Action = ActivityAction.QueryEnter;
}

[Design("检查条件", "需要满足的条件", Sort = 1)]
[Category("配置")]
[DataMember]
public string Condition { get; set; }

protected override async Task ExecuteActionAsync(ProcessflowEventArgs args)
{
// 检查条件
var conditionValue = Flow.DataItems[Condition]?.ToString();

if (string.IsNullOrEmpty(conditionValue))
{
Flow.Logger.LogWarningMessage($"条件 {Condition} 不满足", Name);
// 返回 true 会阻止节点进入
throw new Exception("条件不满足");
}

Flow.Logger.LogMessage($"条件 {Condition} 满足", Name);
}
}

完整流程示例

{
"Name": "动作节点流程",
"Activities": [
{
"Type": "ConditionalActionActivity",
"Name": "条件检查",
"Alias": "CheckCondition",
"Action": "QueryEnter",
"IsSynchronous": true,
"Condition": "RequiredData"
},
{
"Type": "CustomActionActivity",
"Name": "执行动作",
"Alias": "ExecuteAction",
"Action": "Execute",
"IsSynchronous": true,
"ActionParameter": "参数值"
},
{
"Type": "EndActivity",
"Name": "结束",
"Alias": "End"
}
]
}

扩展开发指南

继承层次

Activity (SYC.Flow.Kernel)
└── BusinessActivity
└── ActionActivity
├── ApiCallActivity
├── MethodCallActivity
├── ScriptCallActivity
└── 自定义动作节点

必须实现的方法

方法名说明何时实现
ExecuteActionAsync执行具体的动作逻辑必须实现,这是抽象方法

可重写的方法

方法名用途何时重写
InvokeAsync控制动作的调用方式需要自定义调用逻辑时

自定义动作节点开发步骤

  1. 创建节点类并继承 ActionActivity
[Serializable]
[Design("节点名称", "节点描述", Sort = 排序号)]
[Category("分类名称")]
public class MyActionActivity : ActionActivity
{
// 实现代码
}
  1. 添加配置属性
[Design("属性名称", "属性描述", Sort = 排序号)]
[Category("分类名称")]
[DataMember]
public string MyProperty { get; set; }
  1. 实现 ExecuteActionAsync 方法
protected override async Task ExecuteActionAsync(ProcessflowEventArgs args)
{
// 1. 读取配置和输入
var input = Flow.DataItems["Input"]?.ToString();

// 2. 执行动作逻辑
var result = await DoActionAsync(input, MyProperty);

// 3. 写入输出
Flow.DataItems["Output"] = result;

// 4. 记录日志
Flow.Logger.LogMessage($"动作完成: {result}", Name);
}
  1. 选择执行时机
public MyActionActivity()
{
// 在构造函数中设置执行时机
Action = ActivityAction.Execute; // 或其他时机
IsSynchronous = true; // 或 false
}

注意事项

  • ⚠️ 抽象类: ActionActivity 是抽象类,不能直接实例化
  • ⚠️ 必须实现: 子类必须实现 ExecuteActionAsync 方法
  • ⚠️ 执行时机: 根据业务需求选择合适的 Action 值
  • ⚠️ 同步异步: 同步执行会等待完成,异步执行不会阻塞
  • ⚠️ 异常处理: QueryEnter 和 QueryExit 时的异常会阻止流程继续
  • 💡 最佳实践:
    • 大多数情况使用 Action = Execute
    • 需要条件检查时使用 QueryEnter 或 QueryExit
    • 长时间运行的操作考虑使用异步执行
    • 充分利用日志记录,便于调试

相关节点

常见问题

Q1: 什么时候使用 ActionActivity 而不是 BusinessActivity?

A: 当你需要:

  • 精确控制动作的执行时机
  • 在进入或退出时执行特定操作
  • 实现可以阻止流程继续的条件检查

Q2: Action 属性应该设置为什么值?

A:

  • Execute: 最常用,在节点执行时运行(默认)
  • QueryEnter: 需要在进入前检查条件时
  • Enter: 需要在进入时初始化时
  • QueryExit: 需要在退出前检查条件时
  • Exit: 需要在退出时清理时

Q3: 同步和异步执行有什么区别?

A:

  • 同步 (IsSynchronous=true): 等待动作完成,异常会被捕获
  • 异步 (IsSynchronous=false): 不等待完成,立即继续,适合耗时操作

Q4: 如何阻止流程继续?

A:

  1. 设置 Action = QueryEnter 或 QueryExit
  2. 在 ExecuteActionAsync 中抛出异常
  3. 异常会导致 CanEnterAsync 或 CanExitAsync 返回 false

更新历史

日期版本说明
2025-11-281.0初始版本

本文档最后更新时间: 2025-11-28