跳到主要内容
版本:Next

MethodCallActivity

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

概述​

MethodCallActivity(CSharp调用)用于在流程中调用自定义的 C# 方法。通过实现 IMethodExecuter 接口,开发者可以编写自定义的业务逻辑,并在流程中通过此节点调用。这是一种强大的扩展机制,允许在流程中执行复杂的业务逻辑,而无需修改流程引擎本身。

业务场景​

适用场景​

  • 复杂业务逻辑: 需要执行复杂的计算或业务规则
  • 系统集成: 调用内部系统的服务或组件
  • 数据处理: 对流程数据进行复杂的转换或处理
  • 自定义功能: 实现流程节点无法直接支持的功能
  • 代码复用: 将通用的业务逻辑封装为可复用的执行器

配置说明​

基本配置​

属性名类型必填默认值说明
ExecuterNamestring是-执行对象的完整类名(包含命名空间)
ActionActionType否Execute执行时机
IsSynchronousbool否true是否同步执行

ExecuterName​

说明: IMethodExecuter 实现类的完整类名(包含命名空间),如 "MyApp.Executers.MyCustomExecuter"。

注意事项:

  • 必须是已注册到依赖注入容器的 IMethodExecuter 实现
  • 使用完整的类名(命名空间.类名)
  • 执行器必须在应用启动时注册

流程上下文​

输入参数​

通过 ProcessflowEventArgs 访问所有流程上下文数据。

输出参数​

执行器返回的字典中的所有键值对都会写入流程上下文。

业务逻辑说明​

处理流程​

  1. 从依赖注入容器获取所有 IMethodExecuter 实现
  2. 查找类名匹配 ExecuterName 的执行器
  3. 调用执行器的 Execute 方法
  4. 将返回的数据项写入流程上下文
  5. 记录日志

依赖服务​

服务接口用途
IMethodExecuter自定义方法执行器接口
Flow.ServiceProvider获取注册的执行器

使用示例​

基本示例​

{
"Type": "MethodCallActivity",
"Name": "计算折扣",
"Alias": "CalculateDiscount",
"ExecuterName": "MyApp.Executers.DiscountCalculator",
"Action": "Execute"
}

实现自定义执行器​

using CMS.Plugin.FlowManagement.Abstractions;
using SYC.Flow.Kernel;

namespace MyApp.Executers
{
public class DiscountCalculator : IMethodExecuter
{
public string ExecuterName => "折扣计算器";

public string ExecuterDescription => "根据订单金额计算折扣";

public async Task<Dictionary<string, object>> Execute(ProcessflowEventArgs args)
{
var result = new Dictionary<string, object>();

// 从流程上下文读取数据
var orderAmount = Convert.ToDecimal(args.DataItems["OrderAmount_Value"]);
var customerLevel = args.DataItems["CustomerLevel_Value"]?.ToString();

// 执行业务逻辑
decimal discount = customerLevel switch
{
"VIP" => orderAmount * 0.2m,
"Gold" => orderAmount * 0.15m,
"Silver" => orderAmount * 0.1m,
_ => 0m
};

decimal finalAmount = orderAmount - discount;

// 返回结果
result["Discount_Value"] = discount;
result["FinalAmount_Value"] = finalAmount;

return await Task.FromResult(result);
}
}
}

注册执行器​

// 在 Startup.cs 或 Program.cs 中注册
services.AddTransient<IMethodExecuter, DiscountCalculator>();
services.AddTransient<IMethodExecuter, TaxCalculator>();
services.AddTransient<IMethodExecuter, ShippingCalculator>();

复杂执行器示例​

public class OrderProcessor : IMethodExecuter
{
private readonly IOrderService _orderService;
private readonly IInventoryService _inventoryService;
private readonly ILogger<OrderProcessor> _logger;

public OrderProcessor(
IOrderService orderService,
IInventoryService inventoryService,
ILogger<OrderProcessor> logger)
{
_orderService = orderService;
_inventoryService = inventoryService;
_logger = logger;
}

public string ExecuterName => "订单处理器";
public string ExecuterDescription => "处理订单创建和库存扣减";

public async Task<Dictionary<string, object>> Execute(ProcessflowEventArgs args)
{
var result = new Dictionary<string, object>();

try
{
// 获取订单信息
var orderId = args.DataItems["OrderId_Value"]?.ToString();
var productId = args.DataItems["ProductId_Value"]?.ToString();
var quantity = Convert.ToInt32(args.DataItems["Quantity_Value"]);

// 检查库存
var available = await _inventoryService.CheckAvailability(productId, quantity);
if (!available)
{
result["ProcessResult_Value"] = "Failed";
result["ErrorMessage_Value"] = "库存不足";
return result;
}

// 创建订单
var order = await _orderService.CreateOrder(orderId, productId, quantity);

// 扣减库存
await _inventoryService.DeductInventory(productId, quantity);

result["ProcessResult_Value"] = "Success";
result["OrderNumber_Value"] = order.OrderNumber;
result["OrderStatus_Value"] = order.Status;

_logger.LogInformation($"订单处理成功: {order.OrderNumber}");
}
catch (Exception ex)
{
_logger.LogError(ex, "订单处理失败");
result["ProcessResult_Value"] = "Failed";
result["ErrorMessage_Value"] = ex.Message;
}

return result;
}
}

扩展开发指南​

IMethodExecuter 接口​

public interface IMethodExecuter
{
string ExecuterName { get; }
string ExecuterDescription { get; }
Task<Dictionary<string, object>> Execute(ProcessflowEventArgs args);
}

开发步骤​

  1. 创建执行器类,实现 IMethodExecuter 接口
  2. 实现 Execute 方法,编写业务逻辑
  3. 注册到 DI 容器
  4. 在流程中配置 ExecuterName

最佳实践​

  • 使用依赖注入获取所需服务
  • 返回的字典键名使用 "_Value" 后缀
  • 记录详细的日志
  • 处理异常并返回错误信息
  • 保持执行器职责单一

注意事项​

  • ⚠️ 类名必须完整: 包含命名空间的完整类名
  • ⚠️ 必须注册: 执行器必须注册到 DI 容器
  • ⚠️ 异常处理: 执行器内部应处理异常
  • ⚠️ 返回值: 返回的字典会直接写入流程上下文
  • 💡 建议:
    • 为执行器编写单元测试
    • 使用有意义的 ExecuterName 和 Description
    • 避免在执行器中执行耗时操作

相关节点​

常见问题​

Q1: 如何传递参数给执行器?​

A: 通过 ProcessflowEventArgs.DataItems 访问流程上下文中的所有数据。

Q2: 执行器如何返回数据?​

A: 返回 Dictionary<string, object>,所有键值对会写入流程上下文。

Q3: 执行器找不到怎么办?​

A: 检查:1) 类名是否正确(包含命名空间)2) 是否已注册到 DI 容器。

Q4: 可以在执行器中调用其他服务吗?​

A: 可以,通过构造函数注入所需的服务。

更新历史​

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

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