mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-04 23:36:35 +08:00
取消使用流程上下文自定义的字典数据;更改流程环境接口的输出方式
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
@@ -104,109 +105,97 @@ namespace Serein.NodeFlow
|
||||
var loaderExceptions = ex.LoaderExceptions;
|
||||
foreach (var loaderException in loaderExceptions)
|
||||
{
|
||||
Console.WriteLine(loaderException.Message);
|
||||
SereinEnv.WriteLine(InfoType.ERROR, loaderException.Message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
try
|
||||
#region 获取 DynamicFlow 特性的流程控制器,如果没有退出
|
||||
// Type : 具有 DynamicFlowAttribute 标记的类型
|
||||
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性 (用于生成方法描述时,添加在方法别名中提高可读性)
|
||||
List<(Type Type, string Name)> scanTypes = new List<(Type Type, string Name)>();
|
||||
|
||||
// (Type, string)
|
||||
// Type : 具有 DynamicFlowAttribute 标记的类型
|
||||
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性
|
||||
|
||||
types = types.Where(type => type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute
|
||||
&& dynamicFlowAttribute.Scan).ToList();
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
|
||||
|
||||
#region 获取 DynamicFlow 特性的流程控制器,如果没有退出
|
||||
// Type : 具有 DynamicFlowAttribute 标记的类型
|
||||
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性 (用于生成方法描述时,添加在方法别名中提高可读性)
|
||||
List<(Type Type, string Name)> scanTypes = new List<(Type Type, string Name)>();
|
||||
|
||||
// (Type, string)
|
||||
// Type : 具有 DynamicFlowAttribute 标记的类型
|
||||
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性
|
||||
|
||||
types = types.Where(type => type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute
|
||||
&& dynamicFlowAttribute.Scan).ToList();
|
||||
|
||||
foreach (var type in types)
|
||||
if (type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute)
|
||||
{
|
||||
if (type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute)
|
||||
{
|
||||
scanTypes.Add((type, dynamicFlowAttribute.Name));
|
||||
}
|
||||
scanTypes.Add((type, dynamicFlowAttribute.Name));
|
||||
}
|
||||
if (scanTypes.Count == 0)
|
||||
{
|
||||
// 类型没有流程控制器
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region 创建对应的方法元数据
|
||||
// 从 scanTypes.Type 创建的方法信息
|
||||
// Md : 方法描述
|
||||
// Dd :方法对应的Emit委托
|
||||
List<(MethodDetails Md, DelegateDetails Dd)> detailss = new List<(MethodDetails Md, DelegateDetails Dd)>();
|
||||
|
||||
// 遍历扫描的类型
|
||||
foreach ((var type, var flowName) in scanTypes)
|
||||
{
|
||||
var methodInfos = NodeMethodDetailsHelper.GetMethodsToProcess(type);
|
||||
foreach (var methodInfo in methodInfos) // 遍历流程控制器类型中的方法信息
|
||||
{
|
||||
// 尝试创建
|
||||
if (!NodeMethodDetailsHelper.TryCreateDetails(type, methodInfo, assemblyName,
|
||||
out var md, out var dd)) // 返回的描述
|
||||
{
|
||||
Console.WriteLine($"无法加载方法信息:{assemblyName}-{type}-{methodInfo}");
|
||||
continue;
|
||||
}
|
||||
md.MethodAnotherName = flowName + md.MethodAnotherName; // 方法别名
|
||||
detailss.Add((md, dd));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 检查是否成功加载,如果成功,则真正写入到缓存的集合中
|
||||
if(detailss.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#region 加载成功,缓存所有方法、委托的信息
|
||||
foreach((var md,var dd) in detailss)
|
||||
{
|
||||
MethodDetailss.TryAdd(md.MethodName, md);
|
||||
DelegateDetailss.TryAdd(md.MethodName, dd);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 加载成功,开始获取并记录所有需要自动实例化的类型(在流程启动时)
|
||||
foreach (Type type in types)
|
||||
{
|
||||
if (type.GetCustomAttribute<AutoRegisterAttribute>() is AutoRegisterAttribute attribute)
|
||||
{
|
||||
if (!RegisterTypes.TryGetValue(attribute.Class, out var valus))
|
||||
{
|
||||
valus = new List<Type>();
|
||||
RegisterTypes.TryAdd(attribute.Class, valus);
|
||||
}
|
||||
valus.Add(type);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
if (scanTypes.Count == 0)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
// 类型没有流程控制器
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 创建对应的方法元数据
|
||||
// 从 scanTypes.Type 创建的方法信息
|
||||
// Md : 方法描述
|
||||
// Dd :方法对应的Emit委托
|
||||
List<(MethodDetails Md, DelegateDetails Dd)> detailss = new List<(MethodDetails Md, DelegateDetails Dd)>();
|
||||
|
||||
// 遍历扫描的类型
|
||||
foreach ((var type, var flowName) in scanTypes)
|
||||
{
|
||||
var methodInfos = NodeMethodDetailsHelper.GetMethodsToProcess(type);
|
||||
foreach (var methodInfo in methodInfos) // 遍历流程控制器类型中的方法信息
|
||||
{
|
||||
// 尝试创建
|
||||
if (!NodeMethodDetailsHelper.TryCreateDetails(type, methodInfo, assemblyName,
|
||||
out var md, out var dd)) // 返回的描述
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"无法加载方法信息:{assemblyName}-{type}-{methodInfo}");
|
||||
continue;
|
||||
}
|
||||
md.MethodAnotherName = flowName + md.MethodAnotherName; // 方法别名
|
||||
detailss.Add((md, dd));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 检查是否成功加载,如果成功,则真正写入到缓存的集合中
|
||||
if (detailss.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#region 加载成功,缓存所有方法、委托的信息
|
||||
foreach ((var md, var dd) in detailss)
|
||||
{
|
||||
MethodDetailss.TryAdd(md.MethodName, md);
|
||||
DelegateDetailss.TryAdd(md.MethodName, dd);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 加载成功,开始获取并记录所有需要自动实例化的类型(在流程启动时)
|
||||
foreach (Type type in types)
|
||||
{
|
||||
if (type.GetCustomAttribute<AutoRegisterAttribute>() is AutoRegisterAttribute attribute)
|
||||
{
|
||||
if (!RegisterTypes.TryGetValue(attribute.Class, out var valus))
|
||||
{
|
||||
valus = new List<Type>();
|
||||
RegisterTypes.TryAdd(attribute.Class, valus);
|
||||
}
|
||||
valus.Add(type);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.FlowNode;
|
||||
using Serein.Library.Utils;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -58,7 +59,7 @@ namespace Serein.NodeFlow.Tool
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"尝试卸载程序集[{assemblyName}]发生错误:{ex}");
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"尝试卸载程序集[{assemblyName}]发生错误:{ex}");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -210,7 +211,7 @@ namespace Serein.NodeFlow.Tool
|
||||
{
|
||||
|
||||
return LoadAssembly(typeof(IFlowEnvironment).Assembly, () => {
|
||||
//Console.WriteLine("基础模块不能卸载");
|
||||
//SereinEnv.PrintInfo(InfoType.WRAN, "基础模块不能卸载");
|
||||
});
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -58,7 +60,7 @@ namespace Serein.NodeFlow.Tool
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Unsupported OS.");
|
||||
SereinEnv.WriteLine(InfoType.ERROR, "非预期的OS系统");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +84,7 @@ namespace Serein.NodeFlow.Tool
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Unsupported OS.");
|
||||
SereinEnv.WriteLine(InfoType.ERROR, "非预期的OS系统");
|
||||
}
|
||||
|
||||
foreach (var dir in Directory.GetDirectories(path))
|
||||
@@ -108,18 +110,18 @@ namespace Serein.NodeFlow.Tool
|
||||
if (hModule != IntPtr.Zero)
|
||||
{
|
||||
Nints.Add(hModule);
|
||||
Console.WriteLine($"Loaded: {file}");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"Loaded: {file}");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Failed to load {file}: {Marshal.GetLastWin32Error()}");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error loading {file}: {ex.Message}");
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -140,20 +142,20 @@ namespace Serein.NodeFlow.Tool
|
||||
if (handle != IntPtr.Zero)
|
||||
{
|
||||
Nints.Add(handle);
|
||||
Console.WriteLine($"Loaded: {file}");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"Loaded: {file}");
|
||||
return true;
|
||||
// 可以调用共享库中的函数
|
||||
// IntPtr procAddress = dlsym(handle, "my_function");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Failed to load {file}: {Marshal.GetLastWin32Error()}");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error loading {file}: {ex.Message}");
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ public static class NodeMethodDetailsHelper
|
||||
return false;
|
||||
}
|
||||
|
||||
var methodName = $"{assemblyName}.{type.Name}.{methodInfo.Name}";
|
||||
Console.WriteLine("loading method : " + methodName);
|
||||
var methodName = $"{assemblyName}.{type.Name}.{methodInfo.Name}";
|
||||
SereinEnv.WriteLine(InfoType.INFO, "loading method : " + methodName);
|
||||
|
||||
// 创建参数信息
|
||||
var explicitDataOfParameters = GetExplicitDataOfParameters(methodInfo.GetParameters());
|
||||
@@ -78,7 +78,7 @@ public static class NodeMethodDetailsHelper
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[{methodName}]跳过创建,返回类型非预期的Task<IFlipflopContext<TResult>>。");
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"[{methodName}]跳过创建,返回类型非预期的Task<IFlipflopContext<TResult>>。");
|
||||
methodDetails = null;
|
||||
delegateDetails = null;
|
||||
return false;
|
||||
@@ -86,7 +86,7 @@ public static class NodeMethodDetailsHelper
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[{methodName}]跳过创建,因为触发器方法的返回值并非Task<>,将无法等待。");
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"[{methodName}]跳过创建,因为触发器方法的返回值并非Task<>,将无法等待。");
|
||||
methodDetails = null;
|
||||
delegateDetails = null;
|
||||
return false;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Reflection;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
|
||||
@@ -31,31 +33,31 @@ namespace Serein.NodeFlow.Tool
|
||||
foreach (var prop in objType.GetProperties())
|
||||
{
|
||||
var value = prop.GetValue(obj);
|
||||
Console.WriteLine($"{indent}{prop.Name} (Type: {prop.PropertyType.Name}): {value}");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"{indent}{prop.Name} (Type: {prop.PropertyType.Name}): {value}");
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
if (prop.PropertyType.IsArray) // 处理数组类型
|
||||
{
|
||||
var array = (Array)value;
|
||||
Console.WriteLine($"{indent}{prop.Name} is an array with {array.Length} elements:");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"{indent}{prop.Name} is an array with {array.Length} elements:");
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
var element = array.GetValue(i);
|
||||
if (element != null && element.GetType().IsClass && !(element is string))
|
||||
{
|
||||
Console.WriteLine($"{indent}\tArray[{i}] (Type: {element.GetType().Name}) contains a nested object:");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"{indent}\tArray[{i}] (Type: {element.GetType().Name}) contains a nested object:");
|
||||
PrintObjectProperties(element, indent + "\t\t");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"{indent}\tArray[{i}] (Type: {element?.GetType().Name}): {element}");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"{indent}\tArray[{i}] (Type: {element?.GetType().Name}): {element}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value.GetType().IsClass && !(value is string)) // 处理嵌套对象
|
||||
{
|
||||
Console.WriteLine($"{indent}{prop.Name} contains a nested object:");
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"{indent}{prop.Name} contains a nested object:");
|
||||
PrintObjectProperties(value, indent + "\t");
|
||||
}
|
||||
}
|
||||
@@ -193,7 +195,7 @@ namespace Serein.NodeFlow.Tool
|
||||
if (propInfo == null)
|
||||
{
|
||||
// 属性不存在,打印警告并标记失败
|
||||
Console.WriteLine($"Warning: 属性 '{propName}' 不存在于类型 '{objType.Name}' 中,跳过赋值。");
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"属性 '{propName}' 不存在于类型 '{objType.Name}' 中,跳过赋值。");
|
||||
allSuccessful = false;
|
||||
continue;
|
||||
}
|
||||
@@ -203,7 +205,7 @@ namespace Serein.NodeFlow.Tool
|
||||
if (!IsCompatibleType(targetType, propValue))
|
||||
{
|
||||
// 如果类型不兼容,打印错误并标记失败
|
||||
Console.WriteLine($"Error: 无法将类型 '{propValue?.GetType().Name}' 赋值给属性 '{propName}' (Type: {targetType.Name}),跳过赋值。");
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"无法将类型 '{propValue?.GetType().Name}' 赋值给属性 '{propName}' (Type: {targetType.Name}),跳过赋值。");
|
||||
allSuccessful = false;
|
||||
continue;
|
||||
}
|
||||
@@ -254,7 +256,7 @@ namespace Serein.NodeFlow.Tool
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error: 为属性 '{propName}' 赋值时发生异常:{ex.Message}");
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"为属性 '{propName}' 赋值时发生异常:{ex.Message}");
|
||||
allSuccessful = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user