mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-03 06:46:35 +08:00
示例工程版本提升至net462,项目添加了部分空引用检测逻辑。累了,消不完的空引用警告(T.T)
This commit is contained in:
@@ -41,12 +41,12 @@ namespace Serein.NodeFlow.Base
|
||||
/// <summary>
|
||||
/// 节点guid
|
||||
/// </summary>
|
||||
public string Guid { get; set; }
|
||||
public string Guid { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 显示名称
|
||||
/// </summary>
|
||||
public string DisplayName { get; set; }
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为起点控件
|
||||
@@ -76,7 +76,7 @@ namespace Serein.NodeFlow.Base
|
||||
/// <summary>
|
||||
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
|
||||
/// </summary>
|
||||
public Exception RuningException { get; set; } = null;
|
||||
public Exception? RuningException { get; set; } = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -74,17 +74,17 @@ namespace Serein.NodeFlow.Base
|
||||
|
||||
internal virtual NodeModelBase LoadInfo(NodeInfo nodeInfo)
|
||||
{
|
||||
var node = this;
|
||||
if (node != null)
|
||||
this.Guid = nodeInfo.Guid;
|
||||
if(this.MethodDetails is not null)
|
||||
{
|
||||
node.Guid = nodeInfo.Guid;
|
||||
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
|
||||
{
|
||||
Parameterdata? pd = nodeInfo.ParameterData[i];
|
||||
node.MethodDetails.ExplicitDatas[i].IsExplicitData = pd.State;
|
||||
node.MethodDetails.ExplicitDatas[i].DataValue = pd.Value;
|
||||
this.MethodDetails.ExplicitDatas[i].IsExplicitData = pd.State;
|
||||
this.MethodDetails.ExplicitDatas[i].DataValue = pd.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Serein.NodeFlow.Base
|
||||
if (upstreamNodes[i].DebugSetting.InterruptClass != InterruptClass.None) // 执行触发前
|
||||
{
|
||||
var cancelType = await upstreamNodes[i].DebugSetting.GetInterruptTask();
|
||||
await Console.Out.WriteLineAsync($"[{upstreamNodes[i].MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
await Console.Out.WriteLineAsync($"[{upstreamNodes[i]?.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
}
|
||||
upstreamNodes[i].PreviousNode = currentNode;
|
||||
await upstreamNodes[i].StartExecute(context); // 执行流程节点的上游分支
|
||||
@@ -165,7 +165,7 @@ namespace Serein.NodeFlow.Base
|
||||
if (nextNodes[i].DebugSetting.InterruptClass != InterruptClass.None) // 执行触发前
|
||||
{
|
||||
var cancelType = await nextNodes[i].DebugSetting.GetInterruptTask();
|
||||
await Console.Out.WriteLineAsync($"[{nextNodes[i].MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
await Console.Out.WriteLineAsync($"[{nextNodes[i]?.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
}
|
||||
nextNodes[i].PreviousNode = currentNode;
|
||||
stack.Push(nextNodes[i]);
|
||||
@@ -194,18 +194,22 @@ namespace Serein.NodeFlow.Base
|
||||
// this.NextOrientation = ConnectionType.None;
|
||||
// return null;
|
||||
//}
|
||||
await Console.Out.WriteLineAsync($"[{this.MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
await Console.Out.WriteLineAsync($"[{this.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
MethodDetails md = MethodDetails;
|
||||
MethodDetails? md = MethodDetails;
|
||||
//var del = md.MethodDelegate.Clone();
|
||||
if (md is null)
|
||||
{
|
||||
throw new Exception($"节点{this.Guid}不存在方法信息,请检查是否需要重写节点的ExecutingAsync");
|
||||
}
|
||||
if (!context.Env.TryGetDelegate(md.MethodName, out var del))
|
||||
{
|
||||
throw new Exception("不存在对应委托");
|
||||
throw new Exception($"节点{this.Guid}不存在对应委托");
|
||||
}
|
||||
md.ActingInstance ??= context.Env.IOC.Get(MethodDetails.ActingInstanceType);
|
||||
md.ActingInstance ??= context.Env.IOC.Get(md.ActingInstanceType);
|
||||
object instance = md.ActingInstance;
|
||||
|
||||
var haveParameter = md.ExplicitDatas.Length > 0;
|
||||
@@ -281,7 +285,7 @@ namespace Serein.NodeFlow.Base
|
||||
|
||||
if (ed.IsExplicitData) // 判断是否使用显示的输入参数
|
||||
{
|
||||
if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
|
||||
if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase) && flowData is not null)
|
||||
{
|
||||
// 执行表达式从上一节点获取对象
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(ed.DataValue, flowData, out _);
|
||||
@@ -315,8 +319,6 @@ namespace Serein.NodeFlow.Base
|
||||
}
|
||||
}
|
||||
|
||||
//var attribute = ed.DataType.GetCustomAttribute<EnumTypeConvertorAttribute>();
|
||||
//if (attribute is not null && attribute.EnumType.IsEnum) // 获取枚举转换器中记录的枚举
|
||||
if ( ed.DataType != ed.ExplicitType) // 获取枚举转换器中记录的枚举
|
||||
{
|
||||
if (ed.ExplicitType.IsEnum && Enum.TryParse(ed.ExplicitType, ed.DataValue, out var resultEnum)) // 获取对应的枚举项
|
||||
@@ -339,41 +341,43 @@ namespace Serein.NodeFlow.Base
|
||||
|
||||
try
|
||||
{
|
||||
string? valueStr = inputParameter?.ToString();
|
||||
parameters[i] = ed.DataType switch
|
||||
{
|
||||
//Type t when t == previousDataType => inputParameter, // 上下文
|
||||
Type t when t.IsEnum => Enum.Parse(ed.DataType, ed.DataValue),// 需要枚举
|
||||
Type t when t == typeof(IDynamicContext) => context, // 上下文
|
||||
Type t when t.IsEnum => Enum.Parse(ed.DataType, ed.DataValue),// 需要枚举
|
||||
Type t when t == typeof(string) => inputParameter?.ToString(),
|
||||
Type t when t == typeof(char) && !string.IsNullOrEmpty(valueStr) => char.Parse(valueStr),
|
||||
Type t when t == typeof(bool) && !string.IsNullOrEmpty(valueStr) => inputParameter is not null && bool.Parse(valueStr),
|
||||
Type t when t == typeof(float) && !string.IsNullOrEmpty(valueStr) => float.Parse(valueStr),
|
||||
Type t when t == typeof(decimal) && !string.IsNullOrEmpty(valueStr) => decimal.Parse(valueStr),
|
||||
Type t when t == typeof(double) && !string.IsNullOrEmpty(valueStr) => double.Parse(valueStr),
|
||||
Type t when t == typeof(sbyte) && !string.IsNullOrEmpty(valueStr) => sbyte.Parse(valueStr),
|
||||
Type t when t == typeof(byte) && !string.IsNullOrEmpty(valueStr) => byte.Parse(valueStr),
|
||||
Type t when t == typeof(short) && !string.IsNullOrEmpty(valueStr) => short.Parse(valueStr),
|
||||
Type t when t == typeof(ushort) && !string.IsNullOrEmpty(valueStr) => ushort.Parse(valueStr),
|
||||
Type t when t == typeof(int) && !string.IsNullOrEmpty(valueStr) => int.Parse(valueStr),
|
||||
Type t when t == typeof(uint) && !string.IsNullOrEmpty(valueStr) => uint.Parse(valueStr),
|
||||
Type t when t == typeof(long) && !string.IsNullOrEmpty(valueStr) => long.Parse(valueStr),
|
||||
Type t when t == typeof(ulong) && !string.IsNullOrEmpty(valueStr) => ulong.Parse(valueStr),
|
||||
Type t when t == typeof(nint) && !string.IsNullOrEmpty(valueStr) => nint.Parse(valueStr),
|
||||
Type t when t == typeof(nuint) && !string.IsNullOrEmpty(valueStr) => nuint.Parse(valueStr),
|
||||
//Type t when t == typeof(DateTime) => string.IsNullOrEmpty(valueStr) ? 0 : DateTime.Parse(valueStr),
|
||||
|
||||
Type t when t == typeof(MethodDetails) => md, // 节点方法描述
|
||||
Type t when t == typeof(NodeModelBase) => nodeModel, // 节点实体类
|
||||
Type t when t == typeof(Guid) => new Guid(inputParameter?.ToString()),
|
||||
Type t when t == typeof(DateTime) => DateTime.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(string) => inputParameter?.ToString(),
|
||||
Type t when t == typeof(char) => char.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(bool) => inputParameter is null ? false : bool.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(float) => inputParameter is null ? 0F : float.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(decimal) => inputParameter is null ? 0 : decimal.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(double) => inputParameter is null ? 0 : double.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(sbyte) => inputParameter is null ? 0 : sbyte.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(byte) => inputParameter is null ? 0 : byte.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(short) => inputParameter is null ? 0 : short.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(ushort) => inputParameter is null ? 0U : ushort.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(int) => inputParameter is null ? 0 : int.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(uint) => inputParameter is null ? 0U : uint.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(long) => inputParameter is null ? 0L : long.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(ulong) => inputParameter is null ? 0UL : ulong.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(nint) => inputParameter is null ? 0 : nint.Parse(inputParameter?.ToString()),
|
||||
Type t when t == typeof(nuint) => inputParameter is null ? 0 : nuint.Parse(inputParameter?.ToString()),
|
||||
|
||||
Type t when t.IsArray => (inputParameter as Array)?.Cast<object>().ToList(),
|
||||
Type t when t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>) => inputParameter,
|
||||
Type t when Nullable.GetUnderlyingType(t) != null => inputParameter is null ? null : Convert.ChangeType(inputParameter, Nullable.GetUnderlyingType(t)),
|
||||
_ => inputParameter,
|
||||
// Type t when Nullable.GetUnderlyingType(t) != null => inputParameter is null ? null : Convert.ChangeType(inputParameter, Nullable.GetUnderlyingType(t)),
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex) // 节点参数类型转换异常
|
||||
{
|
||||
parameters[i] = null;
|
||||
parameters[i] = new object();
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
@@ -395,21 +399,25 @@ namespace Serein.NodeFlow.Base
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task MonitorObjExpInterrupt(IDynamicContext context, NodeModelBase nodeModel, object data, int type)
|
||||
private static async Task MonitorObjExpInterrupt(IDynamicContext context, NodeModelBase nodeModel, object? data, int monitorType)
|
||||
{
|
||||
MonitorObjectEventArgs.ObjSourceType sourceType;
|
||||
string key;
|
||||
if(type == 0)
|
||||
string? key;
|
||||
if(monitorType == 0)
|
||||
{
|
||||
key = data.GetType().FullName;
|
||||
key = data?.GetType()?.FullName;
|
||||
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = nodeModel.Guid;
|
||||
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
|
||||
|
||||
}
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.Env.CheckObjMonitorState(key, out List<string> exps)) // 如果新的数据处于查看状态,通知UI进行更新?交给运行环境判断?
|
||||
{
|
||||
context.Env.MonitorObjectNotification(nodeModel.Guid, data, sourceType); // 对象处于监视状态,通知UI更新数据显示
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Serein.NodeFlow
|
||||
public FlowEnvironment()
|
||||
{
|
||||
sereinIOC = new SereinIOC();
|
||||
//ChannelFlowInterrupt = new ChannelFlowInterrupt();
|
||||
ChannelFlowInterrupt = new ChannelFlowInterrupt();
|
||||
//LoadedAssemblyPaths = new List<string>();
|
||||
//LoadedAssemblies = new List<Assembly>();
|
||||
//MethodDetailss = new List<MethodDetails>();
|
||||
@@ -69,67 +69,67 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 加载Dll
|
||||
/// </summary>
|
||||
public event LoadDllHandler OnDllLoad;
|
||||
public event LoadDllHandler? OnDllLoad;
|
||||
|
||||
/// <summary>
|
||||
/// 移除DLL
|
||||
/// </summary>
|
||||
public event RemoteDllHandler OnDllRemote;
|
||||
public event RemoteDllHandler? OnDllRemote;
|
||||
|
||||
/// <summary>
|
||||
/// 项目加载完成
|
||||
/// </summary>
|
||||
public event ProjectLoadedHandler OnProjectLoaded;
|
||||
public event ProjectLoadedHandler? OnProjectLoaded;
|
||||
|
||||
/// <summary>
|
||||
/// 节点连接属性改变事件
|
||||
/// </summary>
|
||||
public event NodeConnectChangeHandler OnNodeConnectChange;
|
||||
public event NodeConnectChangeHandler? OnNodeConnectChange;
|
||||
|
||||
/// <summary>
|
||||
/// 节点创建事件
|
||||
/// </summary>
|
||||
public event NodeCreateHandler OnNodeCreate;
|
||||
public event NodeCreateHandler? OnNodeCreate;
|
||||
|
||||
/// <summary>
|
||||
/// 移除节点事件
|
||||
/// </summary>
|
||||
public event NodeRemoteHandler OnNodeRemote;
|
||||
public event NodeRemoteHandler? OnNodeRemote;
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点变化事件
|
||||
/// </summary>
|
||||
public event StartNodeChangeHandler OnStartNodeChange;
|
||||
public event StartNodeChangeHandler? OnStartNodeChange;
|
||||
|
||||
/// <summary>
|
||||
/// 流程运行完成事件
|
||||
/// </summary>
|
||||
public event FlowRunCompleteHandler OnFlowRunComplete;
|
||||
public event FlowRunCompleteHandler? OnFlowRunComplete;
|
||||
|
||||
/// <summary>
|
||||
/// 被监视的对象改变事件
|
||||
/// </summary>
|
||||
public event MonitorObjectChangeHandler OnMonitorObjectChange;
|
||||
public event MonitorObjectChangeHandler? OnMonitorObjectChange;
|
||||
|
||||
/// <summary>
|
||||
/// 节点中断状态改变事件
|
||||
/// </summary>
|
||||
public event NodeInterruptStateChangeHandler OnNodeInterruptStateChange;
|
||||
public event NodeInterruptStateChangeHandler? OnNodeInterruptStateChange;
|
||||
|
||||
/// <summary>
|
||||
/// 节点触发了中断
|
||||
/// </summary>
|
||||
public event ExpInterruptTriggerHandler OnInterruptTrigger;
|
||||
public event ExpInterruptTriggerHandler? OnInterruptTrigger;
|
||||
|
||||
/// <summary>
|
||||
/// 容器改变
|
||||
/// </summary>
|
||||
public event IOCMembersChangedHandler OnIOCMembersChanged;
|
||||
public event IOCMembersChangedHandler? OnIOCMembersChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 节点需要定位
|
||||
/// </summary>
|
||||
public event NodeLocatedHandler OnNodeLocate;
|
||||
public event NodeLocatedHandler? OnNodeLocate;
|
||||
#endregion
|
||||
|
||||
#region 属性
|
||||
@@ -196,12 +196,12 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 起始节点私有属性
|
||||
/// </summary>
|
||||
private NodeModelBase _startNode;
|
||||
private NodeModelBase? _startNode = null;
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点
|
||||
/// </summary>
|
||||
private NodeModelBase StartNode
|
||||
private NodeModelBase? StartNode
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -209,6 +209,10 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_startNode is not null)
|
||||
{
|
||||
_startNode.IsStart = false;
|
||||
@@ -481,17 +485,19 @@ namespace Serein.NodeFlow
|
||||
|
||||
public bool RemoteDll(string assemblyFullName)
|
||||
{
|
||||
var library = NodeLibrarys.FirstOrDefault(nl => nl.Assembly.FullName.Equals(assemblyFullName));
|
||||
var library = NodeLibrarys.FirstOrDefault(nl => assemblyFullName.Equals(nl.Assembly.FullName));
|
||||
if(library is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var nodes = Nodes.Values.ToDictionary(
|
||||
key => key.MethodDetails.MethodName,
|
||||
value => value
|
||||
);
|
||||
if(nodes.Count == 0)
|
||||
var groupedNodes = Nodes.Values
|
||||
.Where(node => node.MethodDetails is not null)
|
||||
.ToArray()
|
||||
.GroupBy(node => node.MethodDetails!.MethodName)
|
||||
.ToDictionary(
|
||||
key => key.Key,
|
||||
group => group.Count());
|
||||
if(Nodes.Count == 0)
|
||||
{
|
||||
return true; // 当前无节点,可以直接删除
|
||||
}
|
||||
@@ -500,9 +506,12 @@ namespace Serein.NodeFlow
|
||||
{
|
||||
foreach(var md in mds)
|
||||
{
|
||||
if (nodes.ContainsKey(md.MethodName))
|
||||
if(groupedNodes.TryGetValue(md.MethodName,out int count))
|
||||
{
|
||||
return false; // 创建过相关的节点
|
||||
if (count > 0)
|
||||
{
|
||||
return false; // 创建过相关的节点
|
||||
}
|
||||
}
|
||||
}
|
||||
MethodDetailss.Remove(library);
|
||||
@@ -510,7 +519,7 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,9 +694,10 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetDelegate(string methodName, out Delegate del)
|
||||
public bool TryGetDelegate(string methodName, out Delegate? del)
|
||||
{
|
||||
if (MethodDelegates.TryGetValue(methodName, out del))
|
||||
|
||||
if (!string.IsNullOrEmpty(methodName) && MethodDelegates.TryGetValue(methodName, out del))
|
||||
{
|
||||
return del != null;
|
||||
}
|
||||
@@ -742,7 +752,7 @@ namespace Serein.NodeFlow
|
||||
return false;
|
||||
}
|
||||
nodeModel.DebugSetting.InterruptClass = interruptClass;
|
||||
OnNodeInterruptStateChange.Invoke(new NodeInterruptStateChangeEventArgs(nodeGuid, interruptClass));
|
||||
OnNodeInterruptStateChange?.Invoke(new NodeInterruptStateChangeEventArgs(nodeGuid, interruptClass));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -958,11 +968,19 @@ namespace Serein.NodeFlow
|
||||
{
|
||||
// 加载DLL,创建 MethodDetails、实例作用对象、委托方法
|
||||
var assemblyName = type.Assembly.GetName().Name;
|
||||
if (string.IsNullOrEmpty(assemblyName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var methods = MethodDetailsHelperTmp.GetMethodsToProcess(type);
|
||||
foreach(var method in methods)
|
||||
{
|
||||
(var md, var del) = MethodDetailsHelperTmp.CreateMethodDetails(type, method, assemblyName);
|
||||
|
||||
if(md is null || del is null)
|
||||
{
|
||||
Console.WriteLine($"无法加载方法信息:{assemblyName}-{type}-{method}");
|
||||
continue;
|
||||
}
|
||||
if (MethodDelegates.TryAdd(md.MethodName, del))
|
||||
{
|
||||
methodDetails.Add(md);
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
return [];
|
||||
}
|
||||
internal override NodeInfo ToInfo()
|
||||
internal override NodeInfo? ToInfo()
|
||||
{
|
||||
if (MethodDetails is null) return null;
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public static class MethodDetailsHelperTmp
|
||||
/// 创建方法信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static (MethodDetails,Delegate) CreateMethodDetails(Type type, MethodInfo method, string assemblyName)
|
||||
public static (MethodDetails?,Delegate?) CreateMethodDetails(Type type, MethodInfo method, string assemblyName)
|
||||
{
|
||||
|
||||
var methodName = method.Name;
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
|
||||
@@ -78,7 +69,7 @@ namespace Serein.NodeFlow.Tool
|
||||
// 如果类型已经缓存,直接返回缓存的类型
|
||||
if (typeCache.ContainsKey(typeName))
|
||||
{
|
||||
return Activator.CreateInstance(typeCache[typeName]);
|
||||
return Activator.CreateInstance(typeCache[typeName])!;
|
||||
}
|
||||
|
||||
// 定义动态程序集和模块
|
||||
@@ -98,7 +89,7 @@ namespace Serein.NodeFlow.Tool
|
||||
|
||||
if (propValue is IList<Dictionary<string, object>>) // 处理数组类型
|
||||
{
|
||||
var nestedPropValue = (propValue as IList<Dictionary<string, object>>)[0];
|
||||
var nestedPropValue = (propValue as IList<Dictionary<string, object>>)![0];
|
||||
var nestedType = CreateObjectWithProperties(nestedPropValue, $"{propName}Element");
|
||||
propType = nestedType.GetType().MakeArrayType(); // 创建数组类型
|
||||
}
|
||||
@@ -152,7 +143,7 @@ namespace Serein.NodeFlow.Tool
|
||||
typeCache[typeName] = dynamicType;
|
||||
|
||||
// 创建对象实例
|
||||
return Activator.CreateInstance(dynamicType);
|
||||
return Activator.CreateInstance(dynamicType)!;
|
||||
}
|
||||
|
||||
// 方法 2: 递归设置对象的属性值
|
||||
@@ -169,10 +160,10 @@ namespace Serein.NodeFlow.Tool
|
||||
if (value is Dictionary<string, object> nestedProperties)
|
||||
{
|
||||
// 创建嵌套对象
|
||||
var nestedObj = Activator.CreateInstance(propInfo.PropertyType);
|
||||
var nestedObj = Activator.CreateInstance(propInfo!.PropertyType);
|
||||
|
||||
// 递归设置嵌套对象的值
|
||||
SetPropertyValues(nestedObj, nestedProperties);
|
||||
SetPropertyValues(nestedObj!, nestedProperties);
|
||||
|
||||
// 将嵌套对象赋值给属性
|
||||
propInfo.SetValue(obj, nestedObj);
|
||||
@@ -180,7 +171,7 @@ namespace Serein.NodeFlow.Tool
|
||||
else
|
||||
{
|
||||
// 直接赋值给属性
|
||||
propInfo.SetValue(obj, value);
|
||||
propInfo!.SetValue(obj, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,7 +213,7 @@ namespace Serein.NodeFlow.Tool
|
||||
if (propValue is Dictionary<string, object> nestedProperties)
|
||||
{
|
||||
var nestedObj = Activator.CreateInstance(propInfo.PropertyType);
|
||||
if (SetPropertyValuesWithValidation(nestedObj, nestedProperties))
|
||||
if (nestedObj is not null && SetPropertyValuesWithValidation(nestedObj, nestedProperties))
|
||||
{
|
||||
propInfo.SetValue(obj, nestedObj);
|
||||
}
|
||||
@@ -235,22 +226,24 @@ namespace Serein.NodeFlow.Tool
|
||||
{
|
||||
// 获取目标类型的数组元素类型
|
||||
var elementType = propInfo.PropertyType.GetElementType();
|
||||
var array = Array.CreateInstance(elementType, list.Count);
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
if (elementType is not null)
|
||||
{
|
||||
var item = Activator.CreateInstance(elementType);
|
||||
if (SetPropertyValuesWithValidation(item, list[i]))
|
||||
{
|
||||
array.SetValue(item, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
allSuccessful = false; // 赋值失败
|
||||
}
|
||||
}
|
||||
var array = Array.CreateInstance(elementType, list.Count);
|
||||
|
||||
propInfo.SetValue(obj, array);
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
var item = Activator.CreateInstance(elementType);
|
||||
if (item is not null && SetPropertyValuesWithValidation(item, list[i]))
|
||||
{
|
||||
array.SetValue(item, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
allSuccessful = false; // 赋值失败
|
||||
}
|
||||
}
|
||||
propInfo.SetValue(obj, array);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression.Resolver
|
||||
return false;
|
||||
}
|
||||
|
||||
private object GetMemberValue(object? obj, string memberPath)
|
||||
private object? GetMemberValue(object? obj, string memberPath)
|
||||
{
|
||||
string[] members = memberPath[1..].Split('.');
|
||||
foreach (var member in members)
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
}
|
||||
}
|
||||
|
||||
public static SereinConditionResolver ConditionParse(object data, string expression)
|
||||
public static SereinConditionResolver ConditionParse(object? data, string expression)
|
||||
{
|
||||
if (expression.StartsWith('.') || expression.StartsWith('<')) // 表达式前缀属于从上一个节点数据对象获取成员值
|
||||
{
|
||||
@@ -91,7 +91,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
/// <summary>
|
||||
/// 解析对象表达式
|
||||
/// </summary>
|
||||
private static SereinConditionResolver ParseObjectExpression(object data, string expression)
|
||||
private static SereinConditionResolver ParseObjectExpression(object? data, string expression)
|
||||
{
|
||||
var parts = expression.Split(' ');
|
||||
string operatorStr = parts[0]; // 获取操作类型
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
/// <exception cref="NotSupportedException"></exception>
|
||||
public static object Evaluate(string expression, object targetObJ, out bool isChange)
|
||||
public static object? Evaluate(string expression, object targetObJ, out bool isChange)
|
||||
{
|
||||
var parts = expression.Split([' '], 2);
|
||||
if (parts.Length != 2)
|
||||
@@ -84,7 +84,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
/// <param name="methodCall">方法名称</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
private static object InvokeMethod(object target, string methodCall)
|
||||
private static object? InvokeMethod(object target, string methodCall)
|
||||
{
|
||||
var methodParts = methodCall.Split(separator, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (methodParts.Length != 2)
|
||||
@@ -98,12 +98,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
.Select(p => p.Trim())
|
||||
.ToArray();
|
||||
|
||||
var method = target.GetType().GetMethod(methodName);
|
||||
if (method is null)
|
||||
{
|
||||
throw new ArgumentException($"Method {methodName} not found on target.");
|
||||
}
|
||||
|
||||
var method = target.GetType().GetMethod(methodName) ?? throw new ArgumentException($"Method {methodName} not found on target.");
|
||||
var parameterValues = method.GetParameters()
|
||||
.Select((p, index) => Convert.ChangeType(parameters[index], p.ParameterType))
|
||||
.ToArray();
|
||||
@@ -119,15 +114,14 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
/// <param name="memberPath">属性路径</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
private static object GetMember(object target, string memberPath)
|
||||
private static object? GetMember(object? target, string memberPath)
|
||||
{
|
||||
if (target is null) return null;
|
||||
// 分割成员路径,按 '.' 处理多级访问
|
||||
var members = memberPath.Split('.');
|
||||
|
||||
foreach (var member in members)
|
||||
{
|
||||
if (target == null) return null;
|
||||
|
||||
// 检查成员是否包含数组索引,例如 "cars[0]"
|
||||
var arrayIndexStart = member.IndexOf('[');
|
||||
if (arrayIndexStart != -1)
|
||||
@@ -148,22 +142,22 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
}
|
||||
|
||||
// 获取数组或集合对象
|
||||
var arrayProperty = target.GetType().GetProperty(arrayName);
|
||||
if (arrayProperty != null)
|
||||
var arrayProperty = target?.GetType().GetProperty(arrayName);
|
||||
if (arrayProperty is null)
|
||||
{
|
||||
target = arrayProperty.GetValue(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
var arrayField = target.GetType().GetField(arrayName);
|
||||
if (arrayField != null)
|
||||
{
|
||||
target = arrayField.GetValue(target);
|
||||
}
|
||||
else
|
||||
var arrayField = target?.GetType().GetField(arrayName);
|
||||
if (arrayField is null)
|
||||
{
|
||||
throw new ArgumentException($"Member {arrayName} not found on target.");
|
||||
}
|
||||
else
|
||||
{
|
||||
target = arrayField.GetValue(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = arrayProperty.GetValue(target);
|
||||
}
|
||||
|
||||
// 访问数组或集合中的指定索引
|
||||
@@ -191,22 +185,22 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
else
|
||||
{
|
||||
// 处理非数组情况的属性或字段
|
||||
var property = target.GetType().GetProperty(member);
|
||||
if (property != null)
|
||||
var property = target?.GetType().GetProperty(member);
|
||||
if (property is null)
|
||||
{
|
||||
target = property.GetValue(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
var field = target.GetType().GetField(member);
|
||||
if (field != null)
|
||||
{
|
||||
target = field.GetValue(target);
|
||||
}
|
||||
else
|
||||
var field = target?.GetType().GetField(member);
|
||||
if (field is null)
|
||||
{
|
||||
throw new ArgumentException($"Member {member} not found on target.");
|
||||
}
|
||||
else
|
||||
{
|
||||
target = field.GetValue(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = property.GetValue(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,7 +214,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
/// <param name="assignment">属性路径 </param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
private static object SetMember(object target, string assignment)
|
||||
private static object? SetMember(object? target, string assignment)
|
||||
{
|
||||
var parts = assignment.Split(new[] { '=' }, 2);
|
||||
if (parts.Length != 2)
|
||||
@@ -238,7 +232,7 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
|
||||
// 检查是否包含数组索引
|
||||
var arrayIndexStart = member.IndexOf('[');
|
||||
if (arrayIndexStart != -1)
|
||||
if (arrayIndexStart != -1)
|
||||
{
|
||||
// 解析数组名和索引
|
||||
var arrayName = member.Substring(0, arrayIndexStart);
|
||||
@@ -255,24 +249,24 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
}
|
||||
|
||||
// 获取数组或集合
|
||||
var arrayProperty = target.GetType().GetProperty(arrayName);
|
||||
if (arrayProperty != null)
|
||||
var arrayProperty = target?.GetType().GetProperty(arrayName);
|
||||
if (arrayProperty is null)
|
||||
{
|
||||
target = arrayProperty.GetValue(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
var arrayField = target.GetType().GetField(arrayName);
|
||||
if (arrayField != null)
|
||||
{
|
||||
target = arrayField.GetValue(target);
|
||||
}
|
||||
else
|
||||
var arrayField = target?.GetType().GetField(arrayName);
|
||||
if (arrayField is null)
|
||||
{
|
||||
throw new ArgumentException($"Member {arrayName} not found on target.");
|
||||
}
|
||||
else
|
||||
{
|
||||
target = arrayField.GetValue(target);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
target = arrayProperty.GetValue(target);
|
||||
}
|
||||
|
||||
// 获取目标数组或集合中的指定元素
|
||||
if (target is Array array)
|
||||
@@ -299,46 +293,47 @@ namespace Serein.NodeFlow.Tool.SereinExpression
|
||||
else
|
||||
{
|
||||
// 处理非数组情况的属性或字段
|
||||
var property = target.GetType().GetProperty(member);
|
||||
if (property != null)
|
||||
var property = target?.GetType().GetProperty(member);
|
||||
if (property is null)
|
||||
{
|
||||
target = property.GetValue(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
var field = target.GetType().GetField(member);
|
||||
if (field != null)
|
||||
{
|
||||
target = field.GetValue(target);
|
||||
}
|
||||
else
|
||||
var field = target?.GetType().GetField(member);
|
||||
if (field is null)
|
||||
{
|
||||
throw new ArgumentException($"Member {member} not found on target.");
|
||||
}
|
||||
else
|
||||
{
|
||||
target = field.GetValue(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = property.GetValue(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置值
|
||||
var lastMember = members.Last();
|
||||
|
||||
var lastProperty = target.GetType().GetProperty(lastMember);
|
||||
if (lastProperty != null)
|
||||
var lastProperty = target?.GetType().GetProperty(lastMember);
|
||||
if (lastProperty is null)
|
||||
{
|
||||
var convertedValue = Convert.ChangeType(value, lastProperty.PropertyType);
|
||||
lastProperty.SetValue(target, convertedValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
var lastField = target.GetType().GetField(lastMember);
|
||||
if (lastField != null)
|
||||
var lastField = target?.GetType().GetField(lastMember);
|
||||
if (lastField is null)
|
||||
{
|
||||
throw new ArgumentException($"Member {lastMember} not found on target.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var convertedValue = Convert.ChangeType(value, lastField.FieldType);
|
||||
lastField.SetValue(target, convertedValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Member {lastMember} not found on target.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var convertedValue = Convert.ChangeType(value, lastProperty.PropertyType);
|
||||
lastProperty.SetValue(target, convertedValue);
|
||||
}
|
||||
|
||||
return target;
|
||||
|
||||
Reference in New Issue
Block a user