using UIShare.UIViewModel; using UIShare.PubEvent; using Common.Tools; using Logger; using MaterialDesignThemes.Wpf; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using UIShare.GlobalVariable; using static UIShare.UIViewModel.ParameterVM; namespace UIShare { public class StepRunning { private ScopedContext _scopedContext; private SystemConfig _systemConfig; //private Devices _devices; private IContainerProvider containerProvider; private IEventAggregator _eventAggregator; private readonly Dictionary tmpParameters = []; private readonly Stopwatch stepStopwatch = new(); private readonly Stack loopStopwatchStack = new(); private readonly Stack loopStack = new(); public CancellationTokenSource stepCTS = new(); public CancellationTokenSource errorStepCTS = new(); private bool SubSingleStep = false; private Guid TestRoundID; public StepRunning(ScopedContext ScopedContext, SystemConfig systemConfig,IEventAggregator eventAggregator,IContainerProvider containerProvider) { _scopedContext = ScopedContext; _systemConfig = systemConfig; _eventAggregator = eventAggregator; //_devices = containerProvider.Resolve(); } public async Task ExecuteErrorSteps(ProgramVM program, int depth = 0, CancellationToken cancellationToken = default) { int index = 0; bool stepSuccess = false; if (depth == 0) { loopStack.Clear(); loopStopwatchStack.Clear(); ResetAllStepStatus(program.ErrorStepCollection); tmpParameters.Clear(); TestRoundID = Guid.NewGuid(); } foreach (var item in program.Parameters) { tmpParameters.TryAdd(item.ID, item); } while (index < program.ErrorStepCollection.Count) { if (cancellationToken.IsCancellationRequested) { break; } var step = program.ErrorStepCollection[index]; if (!step.IsUsed) { index++; continue; } step.Result = 0; if (step.StepType == "循环开始") { var endStep = program.ErrorStepCollection.FirstOrDefault(x => x.LoopStartStepId == step.ID); if (endStep != null) { endStep.Result = 0; } else { LoggerHelper.ErrorWithNotify("程序循环指令未闭合,请检查后重试"); break; } } // 处理循环开始 if (step.StepType == "循环开始") { Stopwatch loopStopwatch = new(); loopStopwatch.Start(); loopStopwatchStack.Push(loopStopwatch); var context = new LoopContext { LoopCount = step.LoopCount ?? 1, CurrentLoop = 0, StartIndex = index, LoopStartStep = step }; loopStack.Push(context); step.CurrentLoopCount = context.LoopCount; LoggerHelper.InfoWithNotify($"循环开始,共{context.LoopCount}次", depth); index++; } // 处理循环结束 else if (step.StepType == "循环结束") { if (loopStack.Count == 0) { LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth: depth); step.Result = 2; index++; continue; } var context = loopStack.Peek(); context.CurrentLoop++; // 更新循环开始步骤的显示 context.LoopStartStep!.CurrentLoopCount = context.LoopCount - context.CurrentLoop; if (context.CurrentLoop < context.LoopCount) { // 继续循环:跳转到循环开始后的第一条指令 index = context.StartIndex + 1; LoggerHelper.InfoWithNotify($"循环第{context.CurrentLoop}次结束,跳回开始,剩余{context.LoopCount - context.CurrentLoop}次", depth); } else { // 循环结束 loopStack.Pop(); var loopStopwatch = loopStopwatchStack.Peek(); index++; LoggerHelper.InfoWithNotify($"循环结束,共执行{context.LoopCount}次", depth); if (depth == 0 && loopStopwatch.IsRunning) { loopStopwatch.Stop(); step.RunTime = (int)loopStopwatch.ElapsedMilliseconds; step.Result = 1; program.ErrorStepCollection.First(x => x.ID == step.LoopStartStepId).Result = 1; loopStopwatchStack.Pop(); } } } // 处理普通步骤 else { if (depth == 0) { stepStopwatch.Restart(); } if (step.SubProgram != null) { if (_scopedContext.SingleStep)//子程序的单步执行将执行完保存下的所有Method { SubSingleStep = true; _scopedContext.SingleStep = false; } LoggerHelper.InfoWithNotify($"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth); stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken); UpdateCurrentStepResult(step, true, stepSuccess, depth); if (SubSingleStep) { SubSingleStep = false; _scopedContext.SingleStep = true; } } else if (step.Method != null) { LoggerHelper.InfoWithNotify($"开始执行指令 [ {step.Index} ] [ {step.Method!.FullName}.{step.Method.Name} ] ", depth); await ExecuteMethodStep(step, tmpParameters, depth, cancellationToken); stepSuccess = step.Result == 1; if (step.NGGotoStepID != null && !stepSuccess) { var tmp = program.ErrorStepCollection.FirstOrDefault(x => x.ID == step.NGGotoStepID); if (tmp != null) { index = tmp.Index - 2; LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth); } } if (step.OKGotoStepID != null && stepSuccess) { var tmp = program.ErrorStepCollection.FirstOrDefault(x => x.ID == step.OKGotoStepID); if (tmp != null) { index = tmp.Index - 2; LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth); } } } index++; if (depth == 0 && stepStopwatch.IsRunning) { stepStopwatch.Stop(); step.RunTime = (int)stepStopwatch.ElapsedMilliseconds; } } } return loopStack.Count == 0 && stepSuccess; } public async Task ExecuteSteps(ProgramVM program, int depth = 0, CancellationToken cancellationToken = default) { int index = 0; bool stepSuccess = false; if (depth == 0) { loopStack.Clear(); loopStopwatchStack.Clear(); ResetAllStepStatus(program.StepCollection); tmpParameters.Clear(); TestRoundID = Guid.NewGuid(); } foreach (var item in program.Parameters) { tmpParameters.TryAdd(item.ID, item); } while (index < program.StepCollection.Count) { while (_scopedContext.IsStop == true) { await Task.Delay(50); } if (cancellationToken.IsCancellationRequested) { break; } var step = program.StepCollection[index]; if (!step.IsUsed) { index++; continue; } step.Result = 0; if (step.StepType == "循环开始") { var endStep = program.StepCollection.FirstOrDefault(x => x.LoopStartStepId == step.ID); if (endStep != null) { endStep.Result = 0; } else { LoggerHelper.ErrorWithNotify("程序循环指令未闭合,请检查后重试"); break; } } // 处理循环开始 if (step.StepType == "循环开始") { Stopwatch loopStopwatch = new(); loopStopwatch.Start(); loopStopwatchStack.Push(loopStopwatch); var context = new LoopContext { LoopCount = step.LoopCount ?? 1, CurrentLoop = 0, StartIndex = index, LoopStartStep = step }; loopStack.Push(context); step.CurrentLoopCount = context.LoopCount; LoggerHelper.InfoWithNotify($"循环开始({step.Name}),共{context.LoopCount}次", depth); index++; } // 处理循环结束 else if (step.StepType == "循环结束") { if (loopStack.Count == 0) { LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth:depth); step.Result = 2; index++; continue; } var context = loopStack.Peek(); context.CurrentLoop++; // 更新循环开始步骤的显示 context.LoopStartStep!.CurrentLoopCount = context.LoopCount - context.CurrentLoop; if (context.CurrentLoop < context.LoopCount) { // 继续循环:跳转到循环开始后的第一条指令 index = context.StartIndex + 1; LoggerHelper.InfoWithNotify($"循环第{context.CurrentLoop}次结束,跳回开始,剩余{context.LoopCount - context.CurrentLoop}次", depth); } else { // 循环结束 loopStack.Pop(); var loopStopwatch = loopStopwatchStack.Peek(); index++; LoggerHelper.InfoWithNotify($"循环结束,共执行{context.LoopCount}次", depth); if (depth == 0 && loopStopwatch.IsRunning) { loopStopwatch.Stop(); step.RunTime = (int)loopStopwatch.ElapsedMilliseconds; step.Result = 1; program.StepCollection.First(x => x.ID == step.LoopStartStepId).Result = 1; loopStopwatchStack.Pop(); } } } // 处理普通步骤 else { if (depth == 0) { stepStopwatch.Restart(); } if (step.SubProgram != null) { if (_scopedContext.SingleStep)//子程序的单步执行将执行完保存下的所有Method { SubSingleStep = true; _scopedContext.SingleStep = false; } LoggerHelper.InfoWithNotify($"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth); stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken); UpdateCurrentStepResult(step, true, stepSuccess, depth); if (SubSingleStep) { SubSingleStep = false; _scopedContext.SingleStep = true; } } else if (step.Method != null) { LoggerHelper.InfoWithNotify($"开始执行指令 [ {step.Index} ] [ {step.Method!.FullName}.{step.Method.Name} ] ", depth); await ExecuteMethodStep(step, tmpParameters, depth, cancellationToken); stepSuccess = step.Result == 1; if (step.NGGotoStepID != null && !stepSuccess) { var tmp = program.StepCollection.FirstOrDefault(x => x.ID == step.NGGotoStepID); if (tmp != null) { index = tmp.Index - 2; LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth); } } if (step.OKGotoStepID != null && stepSuccess) { var tmp = program.StepCollection.FirstOrDefault(x => x.ID == step.OKGotoStepID); if (tmp != null) { index = tmp.Index - 2; LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth); } } } index++; if (depth == 0 && stepStopwatch.IsRunning) { stepStopwatch.Stop(); step.RunTime = (int)stepStopwatch.ElapsedMilliseconds; } if (_scopedContext.SingleStep) { _scopedContext.IsStop = true; _scopedContext.RunState = "运行"; _scopedContext.SingleStep = false; _eventAggregator.GetEvent().Publish("Play"); } } } return loopStack.Count == 0 && stepSuccess; } public async Task ExecuteMethodStep(StepVM step, Dictionary parameters, int depth, CancellationToken cancellationToken = default) { try { if(_scopedContext.Program.StepCollection.Count>1) _scopedContext.SelectedStep = null; await Task.Delay(_systemConfig.PerformanceLevel); // 1. 查找类型 Type? targetType = null; foreach (var assembly in _scopedContext.Assemblies) { targetType = assembly.GetType(step.Method!.FullName!); if (targetType != null) break; } if (targetType == null) { LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到类型 {step.Method!.FullName}", depth: depth); step.Result = 2; } // 2. 创建实例(仅当方法不是静态时才需要) object? instance = null; bool isMethod = false; // 3. 准备参数 var inputParams = new List(); var paramTypes = new List(); ParameterVM? outputParam = null; foreach (var param in step.Method!.Parameters) { if (param.Category == ParameterCategory.Input) { if (param.Type == typeof(CancellationToken)) { inputParams.Add(stepCTS.Token); paramTypes.Add(param.Type!); continue; } var actualValue = param.GetActualValue(tmpParameters); // 类型转换处理 if (actualValue != null) { if (string.IsNullOrEmpty(actualValue.ToString())) { actualValue = null; } if (actualValue != null && param.Type != null && actualValue.GetType() != param.Type) { try { if (param.Type.IsArray) { // 获取数组元素类型 Type elementType = param.Type.GetElementType()!; // 解析字符串为字符串数组 string[] stringArray = actualValue.ToString()! .Trim('[', ']') .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => s.Trim()) .ToArray(); // 创建目标类型数组 Array array = Array.CreateInstance(elementType, stringArray.Length); // 转换每个元素 for (int i = 0; i < stringArray.Length; i++) { try { // 特殊处理字符串类型 if (elementType == typeof(string)) { array.SetValue(stringArray[i], i); } // 特殊处理枚举类型 else if (elementType.IsEnum) { array.SetValue(Enum.Parse(elementType, stringArray[i]), i); } // 常规类型转换 else { if (stringArray[i] is string s && s.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { // 先转成整数 var intValue = Convert.ToInt64(s, 16); // 再转成目标类型 array.SetValue(Convert.ChangeType(intValue, elementType), i); } else { array.SetValue(Convert.ChangeType(stringArray[i], elementType), i); } } } catch { throw new InvalidCastException($"指令 [ {step.Index} ] 执行错误:元素 '{stringArray[i]}' 无法转换为 {elementType.Name}[]"); } } actualValue = array; } else { if (param.Type.BaseType == typeof(Enum)) { actualValue = Enum.Parse(param.Type, param.Value!.ToString()!); } else { if (actualValue is string s && s.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { // 先转成整数 var intValue = Convert.ToInt64(s, 16); // 再转成目标类型 actualValue = Convert.ChangeType(intValue, param.Type); } else { actualValue = Convert.ChangeType(actualValue, param.Type); } } } } catch (Exception ex) { LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] 执行错误:参数 {param.Name} 类型转换失败: {ex.Message}", depth: depth); } } } inputParams.Add(actualValue); paramTypes.Add(param.Type!); } else if (param.Category == ParameterCategory.Output) { outputParam = param; } } // 4. 获取方法 var method = targetType!.GetMethod( step.Method.Name!, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, null, paramTypes.ToArray(), null ); if (method == null) { LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到方法{step.Method.Name}", depth: depth); step.Result = 2; } // 检查是否是静态方法 bool isStaticMethod = method!.IsStatic; // 如果是实例方法,需要创建实例 if (!isStaticMethod) { try { //instance = _devices.DeviceDic[targetType.Name]; } catch (Exception ex) { LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:创建实例失败 - {ex.Message}", depth: depth); step.Result = 2; } } // 5. 执行方法 object? returnValue = method.Invoke(instance, inputParams.ToArray()); try { // 处理异步方法 if (returnValue is Task task) { await task.ConfigureAwait(false); // 获取结果(如果是Task) if (task.GetType().IsGenericType) { var returnValueProperty = task.GetType().GetProperty("Result"); returnValue = returnValueProperty?.GetValue(task); } else { returnValue = null; } } // 处理VoidTaskreturnValue类型 if (returnValue != null && returnValue.GetType().FullName == "System.Threading.Tasks.VoidTaskreturnValue") { returnValue = null; } } catch (OperationCanceledException) { return; } catch (Exception ex) { LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth); step.Result = 2; return; } // 6. 处理输出 bool paraResult = true; //记录参数上下限是否NG if (outputParam != null) { outputParam.Value = returnValue; var currentPara = outputParam.GetCurrentParameter(tmpParameters); if (currentPara != null) { currentPara.Value = returnValue; var tmp = currentPara.GetResult(); currentPara.Result = tmp.Item1; paraResult = tmp.Item1; if (tmp.Item2 != null) { LoggerHelper.WarnWithNotify(tmp.Item2); } //if (currentPara.IsSave && _scopedContext.Program.Parameters.FirstOrDefault(x => x.ID == currentPara.ID) != null) //{ // _ = SaveDataToDatabase(_scopedContext.Program.ID, currentPara); //} } var returnType = returnValue?.GetType(); if (returnType != null) { if (!returnType.IsArray) { LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = {returnValue} ({returnType.Name})", depth); } else { if (returnValue is IEnumerable enumerable) { var elements = enumerable.Cast().Select(item => item?.ToString() ?? "null"); LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = [ {string.Join(", ", elements)} ] ({returnType.Name})", depth); } } } } LoggerHelper.SuccessWithNotify($"指令 [ {step.Index} ] 执行成功", depth); UpdateCurrentStepResult(step, paraResult: paraResult, depth: depth); } catch (OperationCanceledException) { return; } catch (Exception ex) { LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth); step.Result = 2; return; } } public void ResetAllStepStatus(ObservableCollection StepCollection) { foreach (var step in StepCollection) { step.Result = -1; step.RunTime = null; } } private void UpdateCurrentStepResult(StepVM step, bool paraResult = true, bool stepResult = true, int depth = 0) { if (stepResult && paraResult) { if (string.IsNullOrEmpty(step.OKExpression)) { step.Result = 1; } else { Dictionary paraDic = []; foreach (var item in tmpParameters) { paraDic.TryAdd(item.Value.Name, item.Value.Value!); } if (step.SubProgram != null) { foreach (var item in step.SubProgram.Parameters.Where(x => x.Category == ParameterCategory.Output)) { paraDic.TryAdd(item.Name, item.Value!); } } else if (step.Method != null) { foreach (var item in step.Method.Parameters.Where(x => x.Category == ParameterCategory.Output)) { paraDic.TryAdd(item.Name, item.Value!); } } bool re = ExpressionEvaluator.EvaluateExpression(step.OKExpression, paraDic); step.Result = re ? 1 : 2; if (step.Result == 2) { LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] NG:条件表达式验证失败", depth: depth); } } } else { if (!paraResult) { LoggerHelper.WarnWithNotify("参数限值校验失败", depth: depth); } step.Result = 2; } } #region 私有类 private class LoopContext { public int LoopCount { get; set; } public int CurrentLoop { get; set; } public int StartIndex { get; set; } public StepVM? LoopStartStep { get; set; } } #endregion } }