From 66141533b1861a97d6169ecdf1c04ddca5d68f7f Mon Sep 17 00:00:00 2001
From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com>
Date: Mon, 28 Oct 2024 21:52:45 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E6=B5=81=E7=A8=8B?=
=?UTF-8?q?=E8=BF=90=E8=A1=8C=E4=B8=AD=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Library.Core/NodeFlow/DynamicContext.cs | 68 +++++-
Library.Framework/NodeFlow/DynamicContext.cs | 61 ++++-
Library/Api/IDynamicContext.cs | 23 +-
Library/Ex/FlipflopException.cs | 6 +-
Library/FlowNode/MethodDetails.cs | 2 +-
Library/FlowNode/NodeDebugSetting.cs | 2 +-
Library/FlowNode/NodeModelBaseData.cs | 213 +-----------------
Library/FlowNode/NodeModelBaseFunc.cs | 20 +-
Library/FlowNode/ParameterDetails.cs | 2 +-
.../SerinExpressionEvaluator.cs | 114 ++++++----
NodeFlow/Env/FlowEnvironment.cs | 7 +-
NodeFlow/Env/FlowFunc.cs | 3 +-
NodeFlow/FlowStarter.cs | 57 ++---
NodeFlow/Model/CompositeConditionNode.cs | 10 +-
NodeFlow/Model/SingleActionNode.cs | 9 +
NodeFlow/Model/SingleConditionNode.cs | 28 ++-
NodeFlow/Model/SingleExpOpNode.cs | 12 +-
NodeFlow/Model/SingleFlipflopNode.cs | 10 +-
Serein.BaseNode/Serein.BaseNode.csproj | 30 +++
Serein.BaseNode/SereinBaseNodes.cs | 52 +++++
SereinFlow.sln | 14 +-
WorkBench/App.xaml.cs | 4 +-
WorkBench/MainWindow.xaml | 7 +-
WorkBench/MainWindow.xaml.cs | 4 -
WorkBench/Node/View/ConditionNodeControl.xaml | 46 +++-
.../Node/View/ConditionNodeControl.xaml.cs | 33 ++-
.../ConditionNodeControlViewModel.cs | 54 ++---
27 files changed, 518 insertions(+), 373 deletions(-)
create mode 100644 Serein.BaseNode/Serein.BaseNode.csproj
create mode 100644 Serein.BaseNode/SereinBaseNodes.cs
diff --git a/Library.Core/NodeFlow/DynamicContext.cs b/Library.Core/NodeFlow/DynamicContext.cs
index 436e9f3..081f660 100644
--- a/Library.Core/NodeFlow/DynamicContext.cs
+++ b/Library.Core/NodeFlow/DynamicContext.cs
@@ -36,25 +36,55 @@ namespace Serein.Library.Core.NodeFlow
public ConnectionInvokeType NextOrientation { get; set; }
///
- /// 每个上下文分别存放节点的当前数据
+ /// 每个流程上下文分别存放节点的当前数据
///
- private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary();
+
+ ///
+ /// 每个流程上下文存储运行时节点的调用关系
+ ///
+ private readonly ConcurrentDictionary dictPreviousNodes = new ConcurrentDictionary();
+
+ ///
+ /// 设置运行时上一节点
+ ///
+ /// 当前节点
+ /// 上一节点
+ public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode)
+ {
+ dictPreviousNodes.AddOrUpdate(currentNodeModel, (_)=> PreviousNode, (_,_) => PreviousNode);
+ }
+
+ ///
+ /// 获取当前节点的运行时上一节点
+ ///
+ ///
+ ///
+ public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel)
+ {
+ if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node))
+ {
+ return node;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
///
/// 获取节点当前数据
///
- ///
+ /// 节点
///
public object? GetFlowData(string nodeGuid)
{
- if (string.IsNullOrEmpty(nodeGuid))
- {
- return null;
- }
- if(dictNodeFlowData.TryGetValue(nodeGuid,out var data))
+ if(dictNodeFlowData.TryGetValue(nodeGuid, out var data))
{
return data;
}
+ else
{
return null;
}
@@ -63,14 +93,32 @@ namespace Serein.Library.Core.NodeFlow
///
/// 添加或更新当前节点数据
///
- /// 节点Guid
+ /// 节点
/// 新的数据
- public void AddOrUpdate(string nodeGuid,object? flowData)
+ public void AddOrUpdate(string nodeGuid, object? flowData)
{
// this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData);
this.dictNodeFlowData.AddOrUpdate(nodeGuid, _ => flowData, (_, _) => flowData);
}
+ ///
+ /// 上一节点数据透传到下一节点
+ ///
+ ///
+ public object? TransmissionData(NodeModelBase nodeModel)
+ {
+ if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点
+ {
+ if (dictNodeFlowData.TryGetValue(previousNode.Guid, out var data)) // 其次获取上一节点的数据
+ {
+ return data;
+ //AddOrUpdate(nodeModel.Guid, data); // 然后作为当前节点的数据记录在上下文中
+ }
+ }
+ return null;
+ }
+
+
///
/// 结束流程
///
diff --git a/Library.Framework/NodeFlow/DynamicContext.cs b/Library.Framework/NodeFlow/DynamicContext.cs
index 2e1ad96..b3770ca 100644
--- a/Library.Framework/NodeFlow/DynamicContext.cs
+++ b/Library.Framework/NodeFlow/DynamicContext.cs
@@ -18,7 +18,6 @@ namespace Serein.Library.Framework.NodeFlow
RunState = RunState.Running;
}
-
///
/// 运行环境
@@ -40,10 +39,38 @@ namespace Serein.Library.Framework.NodeFlow
///
private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary dictPreviousNodes = new ConcurrentDictionary();
+
+ ///
+ /// 设置运行时上一节点
+ ///
+ /// 当前节点
+ /// 上一节点
+ public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode)
+ {
+ dictPreviousNodes.AddOrUpdate(currentNodeModel, (n1) => PreviousNode, (n1, n2) => PreviousNode);
+ }
+
+ ///
+ /// 获取当前节点的运行时上一节点
+ ///
+ ///
+ ///
+ public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel)
+ {
+ if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node))
+ {
+ return node;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
///
/// 获取节点当前数据
///
- ///
///
public object GetFlowData(string nodeGuid)
{
@@ -51,6 +78,7 @@ namespace Serein.Library.Framework.NodeFlow
{
return data;
}
+ else
{
return null;
}
@@ -59,14 +87,32 @@ namespace Serein.Library.Framework.NodeFlow
///
/// 添加或更新当前节点数据
///
- /// 节点Guid
+ /// 节点
/// 新的数据
public void AddOrUpdate(string nodeGuid, object flowData)
{
// this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData);
- this.dictNodeFlowData[nodeGuid] = flowData;
+ this.dictNodeFlowData.AddOrUpdate(nodeGuid, n1 => flowData, (n1, n2)=> flowData);
}
+ ///
+ /// 上一节点数据透传到下一节点
+ ///
+ ///
+ public object TransmissionData(NodeModelBase nodeModel)
+ {
+ if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点
+ {
+ if (dictNodeFlowData.TryGetValue(previousNode.Guid, out var data)) // 其次获取上一节点的数据
+ {
+ return data;
+ //AddOrUpdate(nodeModel.Guid, data); // 然后作为当前节点的数据记录在上下文中
+ }
+ }
+ return null;
+ }
+
+
///
/// 结束流程
///
@@ -74,7 +120,11 @@ namespace Serein.Library.Framework.NodeFlow
{
foreach (var nodeObj in dictNodeFlowData.Values)
{
- if (nodeObj != null)
+ if (nodeObj is null)
+ {
+ continue;
+ }
+ else
{
if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable)
{
@@ -85,7 +135,6 @@ namespace Serein.Library.Framework.NodeFlow
this.dictNodeFlowData?.Clear();
RunState = RunState.Completion;
}
-
// public NodeRunCts NodeRunCts { get; set; }
// public ISereinIOC SereinIoc { get; }
//public Task CreateTimingTask(Action action, int time = 100, int count = -1)
diff --git a/Library/Api/IDynamicContext.cs b/Library/Api/IDynamicContext.cs
index f097dc4..54b3f81 100644
--- a/Library/Api/IDynamicContext.cs
+++ b/Library/Api/IDynamicContext.cs
@@ -21,10 +21,24 @@ namespace Serein.Library.Api
RunState RunState { get; }
///
- /// 下一个要执行的节点
+ /// 下一个要执行的节点类别
///
ConnectionInvokeType NextOrientation { get; set; }
+ ///
+ /// 设置节点的运行时上一节点,用以多线程中隔开不同流程的数据
+ ///
+ /// 当前节点
+ /// 运行时上一节点
+ void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode);
+
+ ///
+ /// 获取当前节点的运行时上一节点,用以流程中获取数据
+ ///
+ ///
+ ///
+ NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel);
+
///
/// 获取节点的数据(当前节点需要获取上一节点数据时,需要从 运行时上一节点 的Guid 通过这个方法进行获取
///
@@ -32,6 +46,13 @@ namespace Serein.Library.Api
///
object GetFlowData(string nodeGuid);
+ ///
+ /// 上一节点数据透传到下一节点
+ ///
+ ///
+ object TransmissionData(NodeModelBase nodeModel);
+
+
///
/// 添加或更新当前节点的数据
///
diff --git a/Library/Ex/FlipflopException.cs b/Library/Ex/FlipflopException.cs
index 48cdbc3..960c68d 100644
--- a/Library/Ex/FlipflopException.cs
+++ b/Library/Ex/FlipflopException.cs
@@ -13,11 +13,11 @@ namespace Serein.Library
///
/// 取消触发器当前所在分支的继续执行
///
- Branch,
+ CancelBranch,
///
/// 取消整个触发器流程的再次执行(用于停止全局触发器)
///
- Flow,
+ CancelFlow,
}
///
/// 是否已取消
@@ -27,7 +27,7 @@ namespace Serein.Library
/// 取消类型
///
public CancelClass Type { get; }
- public FlipflopException(string message, bool isCancel = true,CancelClass clsss = CancelClass.Branch) :base(message)
+ public FlipflopException(string message, bool isCancel = true,CancelClass clsss = CancelClass.CancelBranch) :base(message)
{
IsCancel = isCancel;
Type = clsss;
diff --git a/Library/FlowNode/MethodDetails.cs b/Library/FlowNode/MethodDetails.cs
index 67b26e4..53157c5 100644
--- a/Library/FlowNode/MethodDetails.cs
+++ b/Library/FlowNode/MethodDetails.cs
@@ -160,7 +160,7 @@ namespace Serein.Library
StringBuilder sb = new StringBuilder();
sb.AppendLine($"方法别名:{this.MethodAnotherName}");
sb.AppendLine($"方法名称:{this.MethodName}");
- sb.AppendLine($"需要实例:{this.ActingInstanceType.FullName}");
+ sb.AppendLine($"需要实例:{this.ActingInstanceType?.FullName}");
sb.AppendLine($"");
sb.AppendLine($"入参参数信息:");
foreach (var arg in this.ParameterDetailss)
diff --git a/Library/FlowNode/NodeDebugSetting.cs b/Library/FlowNode/NodeDebugSetting.cs
index b3e7cac..7df571d 100644
--- a/Library/FlowNode/NodeDebugSetting.cs
+++ b/Library/FlowNode/NodeDebugSetting.cs
@@ -42,7 +42,7 @@ namespace Serein.Library
///
/// 中断级别,暂时停止继续执行后继分支。
///
- [PropertyInfo(IsNotification = true)] // CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);"
+ [PropertyInfo(IsNotification = true, CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);")] // CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);"
private bool _isInterrupt = false;
///
diff --git a/Library/FlowNode/NodeModelBaseData.cs b/Library/FlowNode/NodeModelBaseData.cs
index 545e89b..c999403 100644
--- a/Library/FlowNode/NodeModelBaseData.cs
+++ b/Library/FlowNode/NodeModelBaseData.cs
@@ -66,8 +66,8 @@ namespace Serein.Library
///
/// 运行时的上一节点
///
- [PropertyInfo]
- private NodeModelBase _previousNode ;
+ //[PropertyInfo]
+ //private NodeModelBase _previousNode ;
///
/// 当前节点执行完毕后需要执行的下一个分支的类别
@@ -86,6 +86,11 @@ namespace Serein.Library
public abstract partial class NodeModelBase : IDynamicFlowNode
{
+ ///
+ /// 加载完成后调用的方法
+ ///
+ public abstract void OnLoading();
+
public NodeModelBase(IFlowEnvironment environment)
{
PreviousNodes = new Dictionary>();
@@ -100,7 +105,6 @@ namespace Serein.Library
}
-
///
/// 不同分支的父节点
///
@@ -111,210 +115,7 @@ namespace Serein.Library
///
public Dictionary> SuccessorNodes { get; }
-
- ///
- /// 控制FlowData在同一时间只会被同一个线程更改。
- ///
- //private readonly ReaderWriterLockSlim _flowDataLock = new ReaderWriterLockSlim();
- //private object _flowData;
- /////
- ///// 当前传递数据(执行了节点对应的方法,才会存在值)。
- /////
- //protected object FlowData
- //{
- // get
- // {
- // _flowDataLock.EnterReadLock();
- // try
- // {
- // return _flowData;
- // }
- // finally
- // {
- // _flowDataLock.ExitReadLock();
- // }
- // }
- // set
- // {
- // _flowDataLock.EnterWriteLock();
- // try
- // {
- // _flowData = value;
- // }
- // finally
- // {
- // _flowDataLock.ExitWriteLock();
- // }
- // }
- //}
}
}
-
- /*
- ///
- /// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
- ///
- public abstract partial class NodeModelBase : IDynamicFlowNode
- {
-
- ///
- /// 节点保留对环境的引用,因为需要在属性更改时通知
- ///
- public IFlowEnvironment Env { get; }
-
- ///
- /// 在画布中的位置
- ///
- public PositionOfUI Position { get; set; }
-
- ///
- /// 附加的调试功能
- ///
- public NodeDebugSetting DebugSetting { get; set; }
-
- ///
- /// 描述节点对应的控件类型
- ///
- public NodeControlType ControlType { get; set; }
-
- ///
- /// 方法描述。不包含Method与委托,需要通过MethodName从环境中获取委托进行调用。
- ///
- public MethodDetails MethodDetails { get; set; }
-
- ///
- /// 标识节点对象全局唯一
- ///
- public string Guid { get; set; }
-
- ///
- /// 显示名称
- ///
- public string DisplayName { get; set; } = string.Empty;
-
- ///
- /// 是否为起点控件
- ///
- public bool IsStart { get; set; }
-
- ///
- /// 运行时的上一节点
- ///
- public NodeModelBase PreviousNode { get; set; }
-
- ///
- /// 当前节点执行完毕后需要执行的下一个分支的类别
- ///
- public ConnectionType NextOrientation { get; set; } = ConnectionType.None;
-
- ///
- /// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
- ///
- public Exception RuningException { get; set; } = null;
-
-
- }*/
-
-
-
- ///
- /// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
- ///
- //public class NodeModelBaseBuilder
- //{
- // public NodeModelBaseBuilder(NodeModelBase builder)
- // {
- // this.ControlType = builder.ControlType;
- // this.MethodDetails = builder.MethodDetails;
- // this.Guid = builder.Guid;
- // this.DisplayName = builder.DisplayName;
- // this.IsStart = builder.IsStart;
- // this.PreviousNode = builder.PreviousNode;
- // this.PreviousNodes = builder.PreviousNodes;
- // this.SucceedBranch = builder.SucceedBranch;
- // this.FailBranch = builder.FailBranch;
- // this.ErrorBranch = builder.ErrorBranch;
- // this.UpstreamBranch = builder.UpstreamBranch;
- // this.FlowState = builder.FlowState;
- // this.RuningException = builder.RuningException;
- // this.FlowData = builder.FlowData;
- // }
-
-
-
- // ///
- // /// 节点对应的控件类型
- // ///
- // public NodeControlType ControlType { get; }
-
- // ///
- // /// 方法描述,对应DLL的方法
- // ///
- // public MethodDetails MethodDetails { get; }
-
- // ///
- // /// 节点guid
- // ///
- // public string Guid { get; }
-
- // ///
- // /// 显示名称
- // ///
- // public string DisplayName { get;}
-
- // ///
- // /// 是否为起点控件
- // ///
- // public bool IsStart { get; }
-
- // ///
- // /// 运行时的上一节点
- // ///
- // public NodeModelBase? PreviousNode { get; }
-
- // ///
- // /// 上一节点集合
- // ///
- // public List PreviousNodes { get; } = [];
-
- // ///
- // /// 下一节点集合(真分支)
- // ///
- // public List SucceedBranch { get; } = [];
-
- // ///
- // /// 下一节点集合(假分支)
- // ///
- // public List FailBranch { get; } = [];
-
- // ///
- // /// 异常分支
- // ///
- // public List ErrorBranch { get; } = [];
-
- // ///
- // /// 上游分支
- // ///
- // public List UpstreamBranch { get; } = [];
-
- // ///
- // /// 当前执行状态(进入真分支还是假分支,异常分支在异常中确定)
- // ///
- // public FlowStateType FlowState { get; set; } = FlowStateType.None;
-
- // ///
- // /// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
- // ///
- // public Exception RuningException { get; set; } = null;
-
- // ///
- // /// 当前传递数据(执行了节点对应的方法,才会存在值)
- // ///
- // public object? FlowData { get; set; } = null;
- //}
-
-
-
-
diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs
index 32facce..93799b8 100644
--- a/Library/FlowNode/NodeModelBaseFunc.cs
+++ b/Library/FlowNode/NodeModelBaseFunc.cs
@@ -173,7 +173,7 @@ namespace Serein.Library
var cancelType = await upstreamNode.DebugSetting.GetInterruptTask();
await Console.Out.WriteLineAsync($"[{upstreamNode.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支");
}
- upstreamNode.PreviousNode = currentNode;
+ context.SetPreviousNode(upstreamNode, currentNode);
await upstreamNode.StartFlowAsync(context); // 执行流程节点的上游分支
if (context.NextOrientation == ConnectionInvokeType.IsError)
{
@@ -186,6 +186,7 @@ namespace Serein.Library
}
// 上游分支执行完成,才执行当前节点
if (IsBradk(context, flowCts)) break; // 退出执行
+ context.NextOrientation = ConnectionInvokeType.None; // 重置上下文状态
object newFlowData = await currentNode.ExecutingAsync(context);
if (IsBradk(context, flowCts)) break; // 退出执行
@@ -204,7 +205,7 @@ namespace Serein.Library
// 筛选出启用的节点的节点
if (nextNodes[i].DebugSetting.IsEnable)
{
- nextNodes[i].PreviousNode = currentNode;
+ context.SetPreviousNode(nextNodes[i], currentNode);
stack.Push(nextNodes[i]);
}
}
@@ -248,7 +249,10 @@ namespace Serein.Library
{
object[] args = await GetParametersAsync(context, this, md);
var result = await dd.InvokeAsync(md.ActingInstance, args);
- context.NextOrientation = ConnectionInvokeType.IsSucceed;
+ if(context.NextOrientation == ConnectionInvokeType.None) // 没有手动设置时,进行自动设置
+ {
+ context.NextOrientation = ConnectionInvokeType.IsSucceed;
+ }
return result;
}
catch (Exception ex)
@@ -342,7 +346,10 @@ namespace Serein.Library
{
if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
{
- var previousFlowData = context.GetFlowData(nodeModel?.PreviousNode?.Guid); // 当前传递的数据
+ var previousNode = context.GetPreviousNode(nodeModel);
+ var previousFlowData = context.GetFlowData(previousNode.Guid); // 当前传递的数据
+
+
// 执行表达式从上一节点获取对象
inputParameter = SerinExpressionEvaluator.Evaluate(ed.DataValue, previousFlowData, out _);
}
@@ -356,7 +363,8 @@ namespace Serein.Library
{
if (ed.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
{
- inputParameter = context.GetFlowData(nodeModel?.PreviousNode?.Guid); // 当前传递的数据
+ var previousNode = context.GetPreviousNode(nodeModel);
+ inputParameter = context.GetFlowData(previousNode.Guid); // 当前传递的数据
}
else if (ed.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
{
@@ -509,6 +517,7 @@ namespace Serein.Library
public static async Task RefreshFlowDataAndExpInterrupt(IDynamicContext context, NodeModelBase nodeModel, object newData = null)
{
string guid = nodeModel.Guid;
+ context.AddOrUpdate(guid, newData); // 上下文中更新数据
if (newData is null)
{
}
@@ -517,7 +526,6 @@ namespace Serein.Library
await MonitorObjExpInterrupt(context, nodeModel, newData, 0); // 首先监视对象
await MonitorObjExpInterrupt(context, nodeModel, newData, 1); // 然后监视节点
//nodeModel.FlowData = newData; // 替换数据
- context.AddOrUpdate(guid, newData); // 上下文中更新数据
}
}
diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs
index 30fa744..42f8b7c 100644
--- a/Library/FlowNode/ParameterDetails.cs
+++ b/Library/FlowNode/ParameterDetails.cs
@@ -174,7 +174,7 @@ namespace Serein.Library
{
if(_convertor is null)
{
- return $"[{this.Index}] {this.Name} : {this.DataType.FullName}";
+ return $"[{this.Index}] {this.Name} : {this.DataType?.FullName}";
}
else
{
diff --git a/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs b/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs
index e583501..9f73aa0 100644
--- a/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs
+++ b/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs
@@ -2,7 +2,10 @@
using System;
using System.Collections.Generic;
using System.Data;
+using System.Diagnostics;
using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
namespace Serein.Library.Utils.SereinExpression
{
@@ -152,53 +155,88 @@ namespace Serein.Library.Utils.SereinExpression
throw new ArgumentException($"Invalid array syntax for member {member}");
}
- // 提取数组索引
- var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
- if (!int.TryParse(indexStr, out int index))
+ var targetType = target?.GetType(); // 目标对象的类型
+ if(targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
- throw new ArgumentException($"Invalid array index '{indexStr}' for member {member}");
- }
- // 获取数组或集合对象
- var arrayProperty = target?.GetType().GetProperty(arrayName);
- if (arrayProperty is null)
- {
- var arrayField = target?.GetType().GetField(arrayName);
- if (arrayField is null)
+ var typetmp = target.GetType().FullName;
+ // 目标是键值对
+ var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
+ var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
+ if(method != null)
{
- throw new ArgumentException($"Member {arrayName} not found on target.");
+ var result = method.Invoke(target, new object[] { indexStr });
+ if(result != null)
+ {
+ return result;
+ }
+ }
+
+ //var dict = target as Dictionary;
+ ////var dict = (Dictionary)target;
+ //var temp = dict[indexStr];
+ ////if (target is Dictionary