增强了实例工程的抽象逻辑

This commit is contained in:
fengjiayi
2024-10-07 15:15:18 +08:00
parent 7a9f7b7bf3
commit 878b1c5893
39 changed files with 1361 additions and 826 deletions

View File

@@ -231,7 +231,7 @@ namespace Serein.NodeFlow.Base
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
await Console.Out.WriteLineAsync($"节点[{this.MethodDetails?.MethodName}]异常:" + ex.Message);
NextOrientation = ConnectionType.IsError;
RuningException = ex;
return null;

View File

@@ -956,7 +956,17 @@ namespace Serein.NodeFlow
List<Type> autoRegisterTypes = assembly.GetTypes().Where(t => t.GetCustomAttribute<AutoRegisterAttribute>() is not null).ToList();
List<Type> scanTypes = assembly.GetTypes().Where(t => t.GetCustomAttribute<DynamicFlowAttribute>()?.Scan == true).ToList();
List<(Type, string)> scanTypes = assembly.GetTypes().Select(t => {
if (t.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute
&& dynamicFlowAttribute.Scan == true)
{
return (t, dynamicFlowAttribute.Name);
}
else
{
return (null, null);
}
}).Where(it => it.t is not null) .ToList();
if (scanTypes.Count == 0)
{
return (null, [], []);
@@ -964,7 +974,7 @@ namespace Serein.NodeFlow
List<MethodDetails> methodDetails = new List<MethodDetails>();
// 遍历扫描的类型
foreach (var type in scanTypes)
foreach ((var type,var flowName ) in scanTypes)
{
// 加载DLL创建 MethodDetails、实例作用对象、委托方法
var assemblyName = type.Assembly.GetName().Name;
@@ -981,6 +991,7 @@ namespace Serein.NodeFlow
Console.WriteLine($"无法加载方法信息:{assemblyName}-{type}-{method}");
continue;
}
md.MethodTips = flowName + md.MethodTips;
if (MethodDelegates.TryAdd(md.MethodName, del))
{
methodDetails.Add(md);

View File

@@ -2,6 +2,7 @@
using Serein.Library.Core.NodeFlow;
using Serein.Library.Entity;
using Serein.Library.Enums;
using Serein.Library.Ex;
using Serein.Library.Utils;
using Serein.Library.Web;
using Serein.NodeFlow.Base;
@@ -385,9 +386,17 @@ namespace Serein.NodeFlow
}
}
}
catch(FlipflopException ex)
{
await Console.Out.WriteLineAsync($"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message);
if (ex.Clsss == FlipflopException.CancelClass.Flow)
{
break;
}
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
await Console.Out.WriteLineAsync(ex.Message);
}
}

View File

@@ -37,24 +37,31 @@ namespace Serein.NodeFlow.Model
throw new Exception("不存在对应委托");
}
object instance = md.ActingInstance;
// Task<IFlipflopContext>? flipflopTask = null;
try
{
// 调用委托并获取结果
//Task<IFlipflopContext> flipflopTask = md.ExplicitDatas.Length switch
//{
// 0 => ((Func<object, Task<IFlipflopContext>>)del).Invoke(md.ActingInstance),
// _ => ((Func<object, object?[]?, Task<IFlipflopContext>>)del).Invoke(md.ActingInstance, GetParameters(context, this, md)), // 执行流程中的触发器方法时获取入参参数
//};
Task<IFlipflopContext> flipflopTask;
if (md.ExplicitDatas.Length == 0)
{
flipflopTask = ((Func<object, Task<IFlipflopContext>>)del).Invoke(md.ActingInstance);
if (del is Func<object, Task<IFlipflopContext>> function)
{
flipflopTask = function.Invoke(md.ActingInstance);
}
else
{
throw new FlipflopException("触发节点非预期的返回类型", true, FlipflopException.CancelClass.Flow);
}
}
else
{
var parameters = GetParameters(context, this, md);
flipflopTask = ((Func<object, object?[]?, Task<IFlipflopContext>>)del).Invoke(md.ActingInstance, parameters);
if(del is Func<object, object?[]?, Task<IFlipflopContext>> function)
{
flipflopTask = function.Invoke(md.ActingInstance, parameters);
}
else
{
throw new FlipflopException("触发节点非预期的返回类型", true,FlipflopException.CancelClass.Flow);
}
}
IFlipflopContext flipflopContext = (await flipflopTask) ?? throw new FlipflopException("没有返回上下文");
@@ -67,14 +74,18 @@ namespace Serein.NodeFlow.Model
}
catch (FlipflopException ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
if(ex.Clsss == FlipflopException.CancelClass.Flow)
{
throw;
}
await Console.Out.WriteLineAsync($"触发器[{this.MethodDetails.MethodName}]异常:" + ex.Message);
NextOrientation = ConnectionType.None;
RuningException = ex;
return null;
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
await Console.Out.WriteLineAsync($"触发器[{this.MethodDetails.MethodName}]异常:" + ex.Message);
NextOrientation = ConnectionType.IsError;
RuningException = ex;
return null;

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Reflection;
using System.Text.RegularExpressions;
namespace Serein.NodeFlow.Tool;
@@ -54,13 +55,14 @@ public static class MethodDetailsHelperTmp
/// <returns></returns>
public static (MethodDetails?,Delegate?) CreateMethodDetails(Type type, MethodInfo method, string assemblyName)
{
var methodName = method.Name;
var attribute = method.GetCustomAttribute<NodeActionAttribute>();
if(attribute is null)
{
return (null, null);
}
//var dllTypeName = $"{assemblyName}.{type.Name}";
var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}";
var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
//// 生成委托
var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型
@@ -68,20 +70,38 @@ public static class MethodDetailsHelperTmp
method.GetParameters(),// 方法参数
method.ReturnType);// 返回值
Type returnType;
if (attribute?.MethodDynamicType == Library.Enums.NodeType.Flipflop)
bool isTask = IsGenericTask(method.ReturnType, out var taskResult);
if (attribute.MethodDynamicType == Library.Enums.NodeType.Flipflop)
{
// 触发器节点
returnType = attribute.ReturnType;
if (!isTask || taskResult != typeof(IFlipflopContext))
{
Console.WriteLine($"触发器节点的返回类型非预期类型,可能会导致流程异常。[{dllTypeMethodName}]当前返回类型为[{method.ReturnType}],而预期的返回类型应为[Task<IFlipflopContext>]");
}
}
else if(isTask)
{
returnType = taskResult;
}
else
{
returnType = method.ReturnType;
}
var dllTypeName = $"{assemblyName}.{type.Name}";
// object instance = Activator.CreateInstance(type);
var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}";
if (string.IsNullOrEmpty(attribute.MethodTips)){
attribute.MethodTips = method.Name;
}
var asyncPrefix = "[异步]"; // IsGenericTask(returnType) ? "[async]" : ;
var methodTips = isTask ? asyncPrefix + attribute.MethodTips : attribute.MethodTips;
var md = new MethodDetails
{
@@ -90,7 +110,7 @@ public static class MethodDetailsHelperTmp
MethodName = dllTypeMethodName,
MethodDynamicType = attribute.MethodDynamicType,
MethodLockName = attribute.LockName,
MethodTips = attribute.MethodTips,
MethodTips = methodTips,
ExplicitDatas = explicitDataOfParameters,
ReturnType = returnType,
};
@@ -99,6 +119,29 @@ public static class MethodDetailsHelperTmp
}
public static bool IsGenericTask(Type returnType, out Type taskResult)
{
// 判断是否为 Task 类型或泛型 Task<T>
if (returnType == typeof(Task))
{
taskResult = returnType;
return true;
}
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
{
// 获取泛型参数类型
Type genericArgument = returnType.GetGenericArguments()[0];
taskResult = genericArgument;
return true;
}
else
{
taskResult = null;
return false;
}
}
private static ConcurrentDictionary<string, (object, MethodInfo)> ConvertorInstance =[];