using Serein.Library; using Serein.Library.Api; using Serein.NodeFlow.Model; using Serein.NodeFlow.Model.Nodes; using Serein.NodeFlow.Services; using System.Text; namespace Serein.NodeFlow.Model.Infos { /// /// 指示流程接口方法需要生成什么代码 /// internal class FlowApiMethodInfo { public FlowApiMethodInfo(SingleFlowCallNode singleFlowCallNode) { NodeModel = singleFlowCallNode; } /// /// 对应的流程节点 /// public SingleFlowCallNode NodeModel { get; } /// /// 生成的接口名称 /// public string ApiMethodName { get; set; } /// /// 返回类型 /// public Type ReturnType { get; set; } /// /// 参数实体信息 /// public List ParamInfos { get; set; } = []; /// /// 参数实体类型名称 /// public string ParamTypeName => $"FlowApiInvoke_{ApiMethodName}"; public class ParamInfo { public ParamInfo(Type type, string paramName) { Type = type; ParamName = paramName; } /// /// /// public Type Type { get; set; } /// /// 参数名称 /// public string ParamName { get; set; } /// /// 注释备注 /// public string Comments { get; set; } } public enum ParamType { Defute, // 仅使用方法参数 HasToken, // 包含取消令牌和方法参数 HasContextAndToken, // 包含上下文、取消令牌和方法参数 } public bool IsVoid => ReturnType == typeof(void); public string ObjPoolName => $"_objPool{ParamTypeName.ToPascalCase()}"; /// /// 生成所需的参数类的签名代码 /// /// public string ToParamterClassSignature() { StringBuilder sb = new StringBuilder(); //sb.AppendCode(2, $"private static readonly global::Microsoft.Extensions.ObjectPool.DefaultObjectPool<{ParamTypeName}> {ObjPoolName} = "); //sb.AppendCode(2, $" new global::Microsoft.Extensions.ObjectPool.DefaultObjectPool<{ParamTypeName}>("); //sb.AppendCode(2, $" new global::Microsoft.Extensions.ObjectPool.DefaultPooledObjectPolicy<{ParamTypeName}>()); "); sb.AppendLine(); var classXmlComments = $"流程接口[{ApiMethodName}]需要的参数类".ToXmlComments(2); sb.AppendCode(2, classXmlComments); sb.AppendCode(2, $"public class {ParamTypeName}"); sb.AppendCode(2, $"{{"); for (int index = 0; index < ParamInfos.Count; index++) { ParamInfo? info = ParamInfos[index]; var argXmlComments = $"[{index}]流程接口参数{(string.IsNullOrWhiteSpace(info.Comments) ? string.Empty : $",{info.Comments}。")}".ToXmlComments(2); sb.AppendCode(3, argXmlComments); sb.AppendCode(3, $"public global::{info.Type.FullName} {info.ParamName.ToPascalCase()} {{ get; set; }}"); } sb.AppendCode(2, $"}}"); return sb.ToString(); } public string ToObjPoolSignature() { StringBuilder sb = new StringBuilder(); sb.AppendCode(2, $"private static readonly global::Microsoft.Extensions.ObjectPool.DefaultObjectPool<{ParamTypeName}> {ObjPoolName} = "); sb.AppendCode(4, $"new global::Microsoft.Extensions.ObjectPool.DefaultObjectPool<{ParamTypeName}>("); sb.AppendCode(5, $"new global::Microsoft.Extensions.ObjectPool.DefaultPooledObjectPolicy<{ParamTypeName}>()); "); return sb.ToString(); } /// /// 生成接口的签名方法 /// /// /// /// public string ToInterfaceMethodSignature(ParamType type) { var taskTypeFullName = $"global::System.Threading.Tasks.Task"; var contextFullName = $"global::{typeof(IFlowContext).FullName}"; var tokenFullName = $"global::{typeof(CancellationToken).FullName}"; var returnContext = IsVoid ? taskTypeFullName : $"{taskTypeFullName}<{ReturnType.FullName}>"; if (type == ParamType.Defute) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}")); return $"{returnContext} {ApiMethodName}({paramSignature});"; } else if (type == ParamType.HasToken) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}")); return $"{returnContext} {ApiMethodName}({tokenFullName} token, {paramSignature});"; } else if (type == ParamType.HasContextAndToken) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}")); return $"{returnContext} {ApiMethodName}({contextFullName} flowContext, {tokenFullName} token, {paramSignature});"; } throw new Exception(); } /// /// 生成实现方法的签名代码 /// /// /// /// public string ToImpleMethodSignature(ParamType type) { var taskTypeFullName = $"global::System.Threading.Tasks.Task"; var contextApiFullName = $"global::{typeof(IFlowContext).FullName}"; var contextImpleFullName = $"global::{typeof(FlowContext).FullName}"; var tokenSourceFullName = $"global::{typeof(CancellationTokenSource).FullName}"; var tokenFullName = $"global::{typeof(CancellationToken).FullName}"; var flowContextPoolName = $"global::{typeof(LightweightFlowControl).FullName}"; string flowEnvironment = nameof(flowEnvironment); string flowContext = nameof(flowContext); string token = nameof(token); var returnTypeContext = IsVoid ? taskTypeFullName : $"{taskTypeFullName}<{ReturnType.FullName}>"; StringBuilder sb = new StringBuilder(); if (IsVoid) { if (type == ParamType.Defute) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{{{p.Type.FullName} {p.ParamName}")); var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName)); sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({paramSignature})"); sb.AppendCode(2, $"{{"); sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文"); sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌"); sb.AppendCode(3, $"try"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"await {ApiMethodName}({flowContext}, cts.Token, {invokeParamSignature}); // 调用目标方法"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"catch (Exception)"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"throw;"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"{flowContext}.{nameof(IFlowContext.Reset)}(); "); sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); "); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); sb.AppendCode(2, $"}}"); return sb.ToString(); } else if (type == ParamType.HasToken) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{{{p.Type.FullName} {p.ParamName}")); var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName)); sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({tokenFullName} {token}, {paramSignature})"); sb.AppendCode(2, $"{{"); sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文"); sb.AppendCode(3, $"try"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法"); sb.AppendCode(4, $"{flowContext}.{nameof(IFlowContext.Reset)}(); "); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"catch (Exception)"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"throw;"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); sb.AppendCode(2, $"}}"); return sb.ToString(); } else if (type == ParamType.HasContextAndToken) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{{{p.Type.FullName} {p.ParamName}")); var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName)); sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({contextApiFullName} {flowContext}, {tokenFullName} token, {paramSignature})"); sb.AppendCode(2, $"{{"); sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消"); sb.AppendCode(3, $"try"); sb.AppendCode(3, $"{{"); sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象"); for (int index = 0; index < ParamInfos.Count; index++) { ParamInfo? info = ParamInfos[index]; sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}"); } sb.AppendCode(3, $"{flowContext}.{nameof(IFlowContext.AddOrUpdate)}(\"{ApiMethodName}\", data);"); sb.AppendCode(3, $"{flowContext}.{nameof(IFlowContext.SetPreviousNode)}(\"{NodeModel.TargetNode.Guid}\", \"{ApiMethodName}\");"); sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");"); sb.AppendCode(3, $"await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"catch (Exception)"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"throw;"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); sb.AppendCode(2, $"}}"); return sb.ToString(); } } else { string flowResult = nameof(flowResult); if (type == ParamType.Defute) { //sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文"); var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}")); var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName)); sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({paramSignature})"); sb.AppendCode(2, $"{{"); sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文"); sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌"); sb.AppendCode(3, $"try"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, cts.{nameof(CancellationTokenSource.Token)}, {invokeParamSignature}); // 调用目标方法"); sb.AppendCode(4, $"return {flowResult};"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"catch (Exception)"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"throw;"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"{flowContext}.{nameof(IFlowContext.Reset)}(); "); sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); "); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); sb.AppendCode(2, $"}}"); return sb.ToString(); } else if (type == ParamType.HasToken) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}")); var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName)); sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({tokenFullName} {token}, {paramSignature})"); sb.AppendCode(2, $"{{"); sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文"); sb.AppendCode(3, $"try"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法"); sb.AppendCode(4, $"return {flowResult};"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"catch (Exception)"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"throw;"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"{flowContext}.{nameof(IFlowContext.Reset)}(); "); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); sb.AppendCode(2, $"}}"); return sb.ToString(); } else if (type == ParamType.HasContextAndToken) { var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}")); var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName)); sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({contextApiFullName} {flowContext}, {tokenFullName} token, {paramSignature})"); sb.AppendCode(2, $"{{"); sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消"); sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象"); for (int index = 0; index < ParamInfos.Count; index++) { ParamInfo? info = ParamInfos[index]; sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}"); // 进行赋值 } sb.AppendCode(3, $"{flowContext}.{nameof(IFlowContext.AddOrUpdate)}(\"{ApiMethodName}\", data);"); sb.AppendCode(3, $"{flowContext}.{nameof(IFlowContext.SetPreviousNode)}(\"{NodeModel.Guid}\", \"{ApiMethodName}\");"); sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");"); sb.AppendCode(3, $"global::{typeof(FlowResult).FullName} {flowResult} = await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法"); if(ReturnType == typeof(object)) { sb.AppendCode(3, $"if ({flowResult}.{nameof(FlowResult.Value)} is null)"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"return null;"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"else", isWrapping :false); } sb.AppendCode(3, $"if ({flowResult}.{nameof(FlowResult.Value)} is global::{ReturnType.FullName} result)"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"return result;"); sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"else"); sb.AppendCode(3, $"{{"); sb.AppendCode(4, $"throw new ArgumentNullException($\"类型转换失败,{{(flowResult.Value is null ? \"返回数据为 null\" : $\"返回数据与需求类型不匹配,当前返回类型为[{{flowResult.Value.GetType().FullName}}。\")}}\");"); sb.AppendCode(3, $"}}"); //sb.AppendCode(3, $"return {flowResult};"); sb.AppendCode(2, $"}}"); return sb.ToString(); // throw new ArgumentNullException($"类型转换失败,{(flowResult.Value is null ? "返回数据为 null" : $"返回数据与需求类型不匹配,当前返回类型为[{flowResult.Value.GetType().FullName}。")}"); } } throw new Exception(); } } }