添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.ProcessResult;
|
||||
using MW.WorkFlow;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public class WorkflowRunCompletedEventArgs : EventArgs
|
||||
{
|
||||
public WorkflowState FinalState { get; }
|
||||
public string Error { get; }
|
||||
public string FailureMessage { get; }
|
||||
public MessageKey FailureMessageKey { get; }
|
||||
public object[] FailureMessageArguments { get; }
|
||||
|
||||
public WorkflowRunCompletedEventArgs(WorkflowState finalState, string error, string failureMessage, MessageKey failureMessageKey, object[] failureMessageArguments)
|
||||
{
|
||||
FinalState = finalState;
|
||||
Error = error;
|
||||
FailureMessage = failureMessage;
|
||||
FailureMessageKey = failureMessageKey;
|
||||
FailureMessageArguments = failureMessageArguments ?? Array.Empty<object>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 封装工作流的启动、停止和状态管理,用于手动流程的复用。
|
||||
/// </summary>
|
||||
public class
|
||||
WorkflowRunner : PropertyChangedBase, IDisposable
|
||||
{
|
||||
private WorkflowEngine _workflowEngine;
|
||||
private bool _isRunning;
|
||||
|
||||
/// <summary>
|
||||
/// 流程是否正在运行
|
||||
/// </summary>
|
||||
public bool IsRunning
|
||||
{
|
||||
get { return _isRunning; }
|
||||
private set { SetAndNotify(ref _isRunning, value); }
|
||||
}
|
||||
|
||||
public event EventHandler<WorkflowRunCompletedEventArgs> RunCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// 运行单个 Activity(自动包装为单步工作流)
|
||||
/// </summary>
|
||||
public Task RunActivityAsync(IActivity activity, WorkflowContext context)
|
||||
{
|
||||
if (activity == null) throw new ArgumentNullException(nameof(activity));
|
||||
|
||||
// 自动构建单步工作流定义
|
||||
var stepId = "SingleStep_" + Guid.NewGuid().ToString("N");
|
||||
var step = new WorkflowStep(stepId, activity);
|
||||
var definition = new WorkflowDefinition(stepId);
|
||||
definition.AddStep(step);
|
||||
|
||||
return RunAsync(definition, context);
|
||||
}
|
||||
|
||||
public Task<WorkflowRunCompletedEventArgs> RunActivityWithResultAsync(IActivity activity, WorkflowContext context)
|
||||
{
|
||||
if (activity == null) throw new ArgumentNullException(nameof(activity));
|
||||
|
||||
var stepId = "SingleStep_" + Guid.NewGuid().ToString("N");
|
||||
var step = new WorkflowStep(stepId, activity);
|
||||
var definition = new WorkflowDefinition(stepId);
|
||||
definition.AddStep(step);
|
||||
|
||||
return RunWithResultAsync(definition, context, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行完整的工作流定义
|
||||
/// </summary>
|
||||
public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context)
|
||||
{
|
||||
await RunWithResultAsync(definition, context, null);
|
||||
}
|
||||
|
||||
public Task<WorkflowRunCompletedEventArgs> RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context)
|
||||
{
|
||||
return RunWithResultAsync(definition, context, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行完整的工作流定义,并支持从指定步骤启动。
|
||||
/// </summary>
|
||||
/// <param name="definition">工作流定义</param>
|
||||
/// <param name="context">工作流上下文</param>
|
||||
/// <param name="startStepId">可选:指定起始步骤ID;为 null/空时从初始步骤启动</param>
|
||||
public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
await RunWithResultAsync(definition, context, startStepId);
|
||||
}
|
||||
|
||||
public async Task<WorkflowRunCompletedEventArgs> RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (definition == null) throw new ArgumentNullException(nameof(definition));
|
||||
if (context == null) throw new ArgumentNullException(nameof(context));
|
||||
|
||||
if (IsRunning)
|
||||
{
|
||||
throw new InvalidOperationException("当前已有流程正在运行,无法重复启动。");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(startStepId) && !definition.GetAllStepIds().Contains(startStepId))
|
||||
{
|
||||
throw new ArgumentException($"指定的起始步骤ID '{startStepId}' 不存在于工作流定义中。", nameof(startStepId));
|
||||
}
|
||||
|
||||
var resolvedStartStepId = ResolveStartStepId(definition, context, startStepId);
|
||||
|
||||
var errorStr = string.Empty;
|
||||
WorkflowState finalState = WorkflowState.Created;
|
||||
MessageKey failureMessageKey = MessageKey.None;
|
||||
object[] failureMessageArguments = Array.Empty<object>();
|
||||
string failureMessage = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
IsRunning = true;
|
||||
_workflowEngine = new WorkflowEngine(definition, context);
|
||||
_workflowEngine.Start(resolvedStartStepId);
|
||||
|
||||
// 异步轮询等待工作流结束
|
||||
// 这样可以不阻塞 UI 线程,同时保持 IsRunning 状态正确
|
||||
while (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
// 捕获最终状态(Dispose 之前)
|
||||
if (_workflowEngine != null)
|
||||
{
|
||||
finalState = _workflowEngine.CurrentState;
|
||||
}
|
||||
|
||||
failureMessageKey = ResolveFailureMessageKey(context);
|
||||
failureMessageArguments = ResolveFailureMessageArguments(context);
|
||||
failureMessage = ResolveFailureMessage(context, failureMessageKey, failureMessageArguments);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 无论正常结束、异常还是被取消,都确保清理资源和复位状态
|
||||
errorStr = _workflowEngine?.LastException?.ToString();
|
||||
IsRunning = false;
|
||||
_workflowEngine?.Dispose();
|
||||
_workflowEngine = null;
|
||||
}
|
||||
|
||||
var completedArgs = new WorkflowRunCompletedEventArgs(finalState, errorStr, failureMessage, failureMessageKey, failureMessageArguments);
|
||||
RunCompleted?.Invoke(this, completedArgs);
|
||||
|
||||
return completedArgs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定步骤启动工作流(语义化封装)。
|
||||
/// </summary>
|
||||
public Task RunFromStepAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(startStepId))
|
||||
throw new ArgumentNullException(nameof(startStepId));
|
||||
|
||||
return RunAsync(definition, context, startStepId);
|
||||
}
|
||||
|
||||
public Task<WorkflowRunCompletedEventArgs> RunFromStepWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(startStepId))
|
||||
throw new ArgumentNullException(nameof(startStepId));
|
||||
|
||||
return RunWithResultAsync(definition, context, startStepId);
|
||||
}
|
||||
|
||||
private string ResolveStartStepId(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(startStepId))
|
||||
{
|
||||
return startStepId;
|
||||
}
|
||||
|
||||
if (!context.TryGetData<string>(WorkflowContextKeys.WorkflowName, out var workflowName) ||
|
||||
string.IsNullOrWhiteSpace(workflowName) ||
|
||||
!context.TryGetData<ProcessResultManager>(WorkflowContextKeys.ProcessResultManager, out var resultManager) ||
|
||||
resultManager == null ||
|
||||
!resultManager.TryGetResumeStepId(workflowName, out var resumeStepId) ||
|
||||
!definition.ContainsStep(resumeStepId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return resumeStepId;
|
||||
}
|
||||
|
||||
private MessageKey ResolveFailureMessageKey(WorkflowContext context)
|
||||
{
|
||||
MessageKey failureMessageKey;
|
||||
if (context.TryGetData<MessageKey>(WorkflowContextKeys.WorkflowFailureMessageKey, out failureMessageKey))
|
||||
{
|
||||
return failureMessageKey;
|
||||
}
|
||||
|
||||
return MessageKey.None;
|
||||
}
|
||||
|
||||
private object[] ResolveFailureMessageArguments(WorkflowContext context)
|
||||
{
|
||||
object[] failureMessageArguments;
|
||||
if (context.TryGetData<object[]>(WorkflowContextKeys.WorkflowFailureMessageArguments, out failureMessageArguments) &&
|
||||
failureMessageArguments != null)
|
||||
{
|
||||
return failureMessageArguments;
|
||||
}
|
||||
|
||||
return Array.Empty<object>();
|
||||
}
|
||||
|
||||
private string ResolveFailureMessage(WorkflowContext context, MessageKey failureMessageKey, object[] failureMessageArguments)
|
||||
{
|
||||
if (failureMessageKey != MessageKey.None)
|
||||
{
|
||||
return LanguageResourceHelper.Format(failureMessageKey, failureMessageArguments);
|
||||
}
|
||||
|
||||
string failureMessage;
|
||||
if (context.TryGetData<string>(WorkflowContextKeys.WorkflowFailureMessage, out failureMessage) &&
|
||||
!string.IsNullOrWhiteSpace(failureMessage))
|
||||
{
|
||||
return failureMessage;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求停止当前流程
|
||||
/// </summary>
|
||||
public async Task StopAsync()
|
||||
{
|
||||
if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
await _workflowEngine.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
_workflowEngine.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
_workflowEngine.Resume();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_workflowEngine?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user