发布Elsa工作流时存储指定活动数据的实现方案咨询
实现Elsa工作流发布时存储特定活动数据的方案
你的中间件方案无法获取活动数据,是因为ASP.NET中间件仅能处理HTTP请求上下文,无法直接访问Elsa工作流的内部模型;且如果工作流是通过内部服务调用发布而非API请求,中间件根本捕获不到操作。以下是基于Elsa自身扩展点的可行方案:
方案一:监听Elsa领域事件
Elsa会在工作流定义创建、更新(发布属于更新操作,生成新版本)时触发领域事件,通过实现事件处理器可以直接获取完整的工作流定义,进而提取活动数据。
1. 编写事件处理器
using Elsa; using Elsa.Events; using Elsa.Models; using System.Linq; using System.Threading; using System.Threading.Tasks; public class WorkflowActivityDataCollector : IDomainEventHandler<WorkflowDefinitionCreatedEvent>, IDomainEventHandler<WorkflowDefinitionUpdatedEvent> { private readonly ICustomActivityDataRepository _activityDataRepo; // 自定义的数据库仓储,用于存储活动数据 public WorkflowActivityDataCollector(ICustomActivityDataRepository activityDataRepo) { _activityDataRepo = activityDataRepo; } public async Task HandleAsync(WorkflowDefinitionCreatedEvent notification, CancellationToken cancellationToken) { await ExtractAndSaveActivityData(notification.WorkflowDefinition, cancellationToken); } public async Task HandleAsync(WorkflowDefinitionUpdatedEvent notification, CancellationToken cancellationToken) { // 仅处理已发布的工作流版本 if (notification.WorkflowDefinition.VersionStatus == VersionStatus.Published) await ExtractAndSaveActivityData(notification.WorkflowDefinition, cancellationToken); } private async Task ExtractAndSaveActivityData(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken) { // 筛选出你需要的特定活动(替换成目标活动的类型名称) var targetActivities = workflowDefinition.Activities .Where(a => a.Type == "Your.Custom.Activity.Type") .ToList(); foreach (var activity in targetActivities) { // 构建要存储的实体对象 var activityData = new CustomActivityData { WorkflowDefinitionId = workflowDefinition.Id, WorkflowVersion = workflowDefinition.Version, ActivityId = activity.Id, ActivityName = activity.Name, // 提取活动配置属性(示例:获取名为"TargetProperty"的属性值) TargetProperty = activity.Properties.TryGetValue("TargetProperty", out var value) ? value.ToString() : null }; await _activityDataRepo.SaveAsync(activityData, cancellationToken); } } }
2. 注册事件处理器
在项目的服务配置中添加:
services.AddScoped<IDomainEventHandler<WorkflowDefinitionCreatedEvent>, WorkflowActivityDataCollector>(); services.AddScoped<IDomainEventHandler<WorkflowDefinitionUpdatedEvent>, WorkflowActivityDataCollector>();
方案二:装饰Elsa的工作流定义存储
通过装饰IWorkflowDefinitionStore接口,在工作流定义保存(发布操作会触发保存)的环节插入自定义逻辑,直接处理工作流模型。
1. 编写装饰器类
using Elsa.Models; using Elsa.Persistence.Stores; using System.Threading; using System.Threading.Tasks; public class WorkflowDefinitionStoreDecorator : IWorkflowDefinitionStore { private readonly IWorkflowDefinitionStore _innerStore; private readonly ICustomActivityDataRepository _activityDataRepo; public WorkflowDefinitionStoreDecorator(IWorkflowDefinitionStore innerStore, ICustomActivityDataRepository activityDataRepo) { _innerStore = innerStore; _activityDataRepo = activityDataRepo; } public async Task<WorkflowDefinition> SaveAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default) { // 先让Elsa完成工作流定义的保存 var savedWorkflow = await _innerStore.SaveAsync(workflowDefinition, cancellationToken); // 提取并保存特定活动数据,逻辑同方案一 var targetActivities = savedWorkflow.Activities .Where(a => a.Type == "Your.Custom.Activity.Type") .ToList(); foreach (var activity in targetActivities) { var activityData = new CustomActivityData { WorkflowDefinitionId = savedWorkflow.Id, WorkflowVersion = savedWorkflow.Version, ActivityId = activity.Id, // 填充其他属性... }; await _activityDataRepo.SaveAsync(activityData, cancellationToken); } return savedWorkflow; } // 实现接口的其他方法,直接委托给内部存储实例 public Task<WorkflowDefinition?> GetByIdAsync(string id, VersionOptions versionOptions, CancellationToken cancellationToken = default) => _innerStore.GetByIdAsync(id, versionOptions, cancellationToken); public Task DeleteAsync(string id, CancellationToken cancellationToken = default) => _innerStore.DeleteAsync(id, cancellationToken); // 剩余接口方法同理,全部转发给_innerStore }
2. 注册装饰器
在服务配置中添加:
services.Decorate<IWorkflowDefinitionStore, WorkflowDefinitionStoreDecorator>();
关键注意事项
- 活动类型匹配:目标活动的类型名称需准确,自定义活动的类型默认是类的完整命名空间+类名,也可通过活动类上的
[Activity(TypeName = "CustomName")]特性自定义。 - 版本判断:如果只需要处理正式发布的版本,需通过
WorkflowDefinition.VersionStatus == VersionStatus.Published过滤。 - 仓储实现:
ICustomActivityDataRepository是你需要自行实现的数据库操作类,用于将活动数据写入目标集合。
内容的提问来源于stack exchange,提问作者Maruful Islam
相关产品推荐
相关产品推荐

