From bcbf6cb99280deb18d1236288a80d32c18013897 Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Mon, 16 Sep 2024 19:53:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86IOC=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=88=A0=E9=99=A4=E4=BA=86=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E6=8E=92=E9=99=A4=E7=9A=84=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library.Core/Flow/Api.cs | 13 - Library.Core/Flow/Attribute.cs | 73 -- Library.Core/Flow/DynamicContext.cs | 168 ---- Library.Core/Flow/MethodDetails.cs | 240 ------ Library.Core/Flow/NodeFlowStarter.cs | 171 ---- .../Flow/NodeModel/CompositeActionNode.cs | 51 -- .../Flow/NodeModel/CompositeConditionNode.cs | 67 -- .../Flow/NodeModel/CompositeLoopNode.cs | 6 - Library.Core/Flow/NodeModel/NodeBase.cs | 510 ------------ .../Flow/NodeModel/SingleActionNode.cs | 68 -- .../Flow/NodeModel/SingleConditionNode.cs | 71 -- .../Flow/NodeModel/SingleExpOpNode.cs | 35 - .../Flow/NodeModel/SingleFlipflopNode.cs | 12 - .../Flow/SerinExpression/ConditionResolver.cs | 337 -------- .../SerinExpression/SerinConditionParser.cs | 329 -------- .../SerinExpressionEvaluator.cs | 214 ----- Library.Core/Flow/Tool/DelegateGenerator.cs | 192 ----- Library.Core/Flow/Tool/DynamicTool.cs | 194 ----- Library.Core/Flow/Tool/ExpressionHelper.cs | 740 ----------------- Library.Core/Flow/Tool/TcsSignal.cs | 80 -- Library.Core/IOC/SereinIoc.cs | 373 --------- .../SerinExpression/ConditionResolver.cs | 337 -------- .../SerinExpression/SerinConditionParser.cs | 338 -------- Library.Core/ServiceContainer.cs | 418 ---------- Library.Core/Tool/DataHelper.cs | 185 ----- Library.Framework/Http/Attribute.cs | 167 ---- Library.Framework/Http/ControllerBase.cs | 19 - Library.Framework/Http/Router.cs | 761 ------------------ Library.Framework/Http/WebAPIAttribute.cs | 196 ----- Library.Framework/IOC/SereinIoc.cs | 378 --------- Library.Framework/NodeFlow/Api.cs | 13 - .../NodeFlow/DynamicNodeFrameworkType.cs | 38 - Library.Framework/NodeFlow/FlowStateType.cs | 25 - Library.Framework/NodeFlow/Tool/Attribute.cs | 8 - .../NodeFlow/Tool/DynamicTool.cs | 194 ----- Library.Framework/NodeFlow/Tool/TcsSignal.cs | 65 -- Library.Framework/Tool/DataHelper.cs | 186 ----- Library/Api/ISereinIoc.cs | 9 +- Library/Base/NodeBase.cs | 83 -- Library/Base/NodeModelBaseData.cs | 110 --- Library/Base/NodeModelBaseFunc.cs | 480 ----------- Library/Serein.Library.csproj | 11 +- Library/Utils/SereinIoc.cs | 234 ++++-- .../SerinExpression/ConditionResolver.cs | 338 -------- .../SerinExpressionEvaluator.cs | 216 ----- NodeFlow/Base/NodeModelBaseFunc.cs | 2 +- NodeFlow/ConnectionType.cs | 30 - NodeFlow/DynamicContext.cs | 230 ------ NodeFlow/FlowEnvironment.cs | 62 +- NodeFlow/FlowStarter.cs | 2 +- NodeFlow/MethodDetails.cs | 241 ------ NodeFlow/Model/SingleConditionNode.cs | 4 +- NodeFlow/Model/SingleExpOpNode.cs | 2 +- NodeFlow/SerinExpression/ConditionResolver.cs | 337 -------- .../SerinExpression/SerinConditionParser.cs | 329 -------- .../SerinExpressionEvaluator.cs | 214 ----- NodeFlow/Tool/Attribute.cs | 73 -- NodeFlow/Tool/DynamicTool.cs | 202 ----- NodeFlow/Tool/NodeModelBaseFunc.cs | 460 ----------- .../Resolver/BoolConditionResolver.cs | 38 + .../Resolver/MemberConditionResolver.cs | 53 ++ .../Resolver/MemberStringConditionResolver.cs | 76 ++ .../Resolver/PassConditionResolver.cs | 38 + .../Resolver/StringConditionResolver.cs | 80 ++ .../Resolver/ValueTypeConditionResolver.cs | 100 +++ .../SereinExpression/SereinConditionParser.cs | 92 ++- .../SereinConditionResolver.cs | 12 + .../SerinExpressionEvaluator.cs | 46 +- .../Tool/SerinExpression/ConditionResolver.cs | 337 -------- .../SerinExpression/SerinConditionParser.cs | 341 -------- .../SerinExpressionEvaluator.cs | 216 ----- NodeFlow/Tool/TcsSignal.cs | 64 -- 72 files changed, 702 insertions(+), 11732 deletions(-) delete mode 100644 Library.Core/Flow/Api.cs delete mode 100644 Library.Core/Flow/Attribute.cs delete mode 100644 Library.Core/Flow/DynamicContext.cs delete mode 100644 Library.Core/Flow/MethodDetails.cs delete mode 100644 Library.Core/Flow/NodeFlowStarter.cs delete mode 100644 Library.Core/Flow/NodeModel/CompositeActionNode.cs delete mode 100644 Library.Core/Flow/NodeModel/CompositeConditionNode.cs delete mode 100644 Library.Core/Flow/NodeModel/CompositeLoopNode.cs delete mode 100644 Library.Core/Flow/NodeModel/NodeBase.cs delete mode 100644 Library.Core/Flow/NodeModel/SingleActionNode.cs delete mode 100644 Library.Core/Flow/NodeModel/SingleConditionNode.cs delete mode 100644 Library.Core/Flow/NodeModel/SingleExpOpNode.cs delete mode 100644 Library.Core/Flow/NodeModel/SingleFlipflopNode.cs delete mode 100644 Library.Core/Flow/SerinExpression/ConditionResolver.cs delete mode 100644 Library.Core/Flow/SerinExpression/SerinConditionParser.cs delete mode 100644 Library.Core/Flow/SerinExpression/SerinExpressionEvaluator.cs delete mode 100644 Library.Core/Flow/Tool/DelegateGenerator.cs delete mode 100644 Library.Core/Flow/Tool/DynamicTool.cs delete mode 100644 Library.Core/Flow/Tool/ExpressionHelper.cs delete mode 100644 Library.Core/Flow/Tool/TcsSignal.cs delete mode 100644 Library.Core/IOC/SereinIoc.cs delete mode 100644 Library.Core/SerinExpression/ConditionResolver.cs delete mode 100644 Library.Core/SerinExpression/SerinConditionParser.cs delete mode 100644 Library.Core/ServiceContainer.cs delete mode 100644 Library.Core/Tool/DataHelper.cs delete mode 100644 Library.Framework/Http/Attribute.cs delete mode 100644 Library.Framework/Http/ControllerBase.cs delete mode 100644 Library.Framework/Http/Router.cs delete mode 100644 Library.Framework/Http/WebAPIAttribute.cs delete mode 100644 Library.Framework/IOC/SereinIoc.cs delete mode 100644 Library.Framework/NodeFlow/Api.cs delete mode 100644 Library.Framework/NodeFlow/DynamicNodeFrameworkType.cs delete mode 100644 Library.Framework/NodeFlow/FlowStateType.cs delete mode 100644 Library.Framework/NodeFlow/Tool/Attribute.cs delete mode 100644 Library.Framework/NodeFlow/Tool/DynamicTool.cs delete mode 100644 Library.Framework/NodeFlow/Tool/TcsSignal.cs delete mode 100644 Library.Framework/Tool/DataHelper.cs delete mode 100644 Library/Base/NodeBase.cs delete mode 100644 Library/Base/NodeModelBaseData.cs delete mode 100644 Library/Base/NodeModelBaseFunc.cs delete mode 100644 Library/Utils/SerinExpression/ConditionResolver.cs delete mode 100644 Library/Utils/SerinExpression/SerinExpressionEvaluator.cs delete mode 100644 NodeFlow/ConnectionType.cs delete mode 100644 NodeFlow/DynamicContext.cs delete mode 100644 NodeFlow/MethodDetails.cs delete mode 100644 NodeFlow/SerinExpression/ConditionResolver.cs delete mode 100644 NodeFlow/SerinExpression/SerinConditionParser.cs delete mode 100644 NodeFlow/SerinExpression/SerinExpressionEvaluator.cs delete mode 100644 NodeFlow/Tool/Attribute.cs delete mode 100644 NodeFlow/Tool/DynamicTool.cs delete mode 100644 NodeFlow/Tool/NodeModelBaseFunc.cs create mode 100644 NodeFlow/Tool/SereinExpression/Resolver/BoolConditionResolver.cs create mode 100644 NodeFlow/Tool/SereinExpression/Resolver/MemberConditionResolver.cs create mode 100644 NodeFlow/Tool/SereinExpression/Resolver/MemberStringConditionResolver.cs create mode 100644 NodeFlow/Tool/SereinExpression/Resolver/PassConditionResolver.cs create mode 100644 NodeFlow/Tool/SereinExpression/Resolver/StringConditionResolver.cs create mode 100644 NodeFlow/Tool/SereinExpression/Resolver/ValueTypeConditionResolver.cs rename Library/Utils/SerinExpression/SerinConditionParser.cs => NodeFlow/Tool/SereinExpression/SereinConditionParser.cs (81%) create mode 100644 NodeFlow/Tool/SereinExpression/SereinConditionResolver.cs rename {Library.Core/SerinExpression => NodeFlow/Tool/SereinExpression}/SerinExpressionEvaluator.cs (82%) delete mode 100644 NodeFlow/Tool/SerinExpression/ConditionResolver.cs delete mode 100644 NodeFlow/Tool/SerinExpression/SerinConditionParser.cs delete mode 100644 NodeFlow/Tool/SerinExpression/SerinExpressionEvaluator.cs delete mode 100644 NodeFlow/Tool/TcsSignal.cs diff --git a/Library.Core/Flow/Api.cs b/Library.Core/Flow/Api.cs deleted file mode 100644 index a62632a..0000000 --- a/Library.Core/Flow/Api.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.Flow -{ - public interface IDynamicFlowNode - { - } - -} diff --git a/Library.Core/Flow/Attribute.cs b/Library.Core/Flow/Attribute.cs deleted file mode 100644 index 942f11d..0000000 --- a/Library.Core/Flow/Attribute.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.Flow -{ - - public enum DynamicNodeType - { - /// - /// 初始化 - /// - Init, - /// - /// 开始载入 - /// - Loading, - /// - /// 结束 - /// - Exit, - - /// - /// 触发器 - /// - Flipflop, - /// - /// 条件节点 - /// - Condition, - /// - /// 动作节点 - /// - Action, - } - - - - /// - /// 用来判断一个类是否需要注册并构建实例(单例模式场景使用) - /// - [AttributeUsage(AttributeTargets.Class)] - public class DynamicFlowAttribute(bool scan = true) : Attribute - { - public bool Scan { get; set; } = scan; - } - - /// - /// 标记一个方法是什么类型,加载dll后用来拖拽到画布中 - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public class MethodDetailAttribute(DynamicNodeType methodDynamicType, - string methodTips = "", - bool scan = true, - string lockName = "") : Attribute - { - public bool Scan { get; set; } = scan; - public string MethodTips { get; } = methodTips; - public DynamicNodeType MethodDynamicType { get; } = methodDynamicType; - public string LockName { get; } = lockName; - } - - /// - /// 是否为显式参数 - /// - [AttributeUsage(AttributeTargets.Parameter)] - public class ExplicitAttribute : Attribute // where TEnum : Enum - { - } - -} diff --git a/Library.Core/Flow/DynamicContext.cs b/Library.Core/Flow/DynamicContext.cs deleted file mode 100644 index a0bb924..0000000 --- a/Library.Core/Flow/DynamicContext.cs +++ /dev/null @@ -1,168 +0,0 @@ -using DynamicDemo.Node; -using Serein.Library.IOC; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using static System.Collections.Specialized.BitVector32; -using static System.Runtime.InteropServices.JavaScript.JSType; - -namespace Serein.Flow -{ - - public enum FfState - { - Succeed, - Cancel, - } - /// - /// 触发器上下文 - /// - public class FlipflopContext - { - public FfState State { get; set; } - public object? Data { get; set; } - /*public FlipflopContext() - { - State = FfState.Cancel; - }*/ - public FlipflopContext(FfState ffState,object? data = null) - { - State = ffState; - Data = data; - } - } - - - /// - /// 动态流程上下文 - /// - - public class DynamicContext(IServiceContainer serviceContainer) - - { - - private readonly string contextGuid = "";//System.Guid.NewGuid().ToString(); - - public IServiceContainer ServiceContainer { get; } = serviceContainer; - private List InitServices { get; set; } = []; - - // private ConcurrentDictionary ContextData { get; set; } = []; - - //public void SetFlowData(object data) - //{ - // var threadId = Thread.CurrentThread.ManagedThreadId.ToString(); - // var name = $"{threadId}.{contextGuid}FlowData"; - // SetData(name,data); - //} - //public object GetFlowData(bool IsRetain = false) - //{ - // var threadId = Thread.CurrentThread.ManagedThreadId.ToString(); - // var name = $"{threadId}.{contextGuid}FlowData"; - // if (IsRetain) - // { - // return GetData(name); - // } - // else - // { - // return GetAndRemoteData(name); - - // } - //} - - - public void InitService() - { - InitService(typeof(T)); - } - public void InitService(Type type) - { - if (!InitServices.Contains(type)) - { - InitServices.Add(type); - } - else - { - //throw new Exception("初始化时试图添加已存在的类型:"+type.Name); - Console.WriteLine("初始化时试图添加已存在的类型:" + type.Name); - } - } - public void Biuld() - { - foreach (var item in InitServices) - { - ServiceContainer.Register(item); - } - ServiceContainer.Build(); - } - - //public object? RemoveData(string key) - //{ - // if (ContextData.Remove(key, out var data)) - // { - // return data; - // } - // return null; - //} - - //public void SetData(string key, T value) - //{ - // ContextData[key] = value; - //} - - //public T? GetData(string key) - //{ - // if (ContextData.TryGetValue(key, out object? value)) - // { - // if(value == null) - // { - // return default; - // } - // if (value.GetType() == typeof(T)) - // { - // return (T)value; - // } - - // } - // return default; - //} - - //public object? GetData(string key) - //{ - // if (ContextData.TryGetValue(key, out object? value)) - // { - // return value; - // } - // return null; - //} - - - //public ConcurrentDictionary FlipFlopTasks { get; set; } = []; - - public NodeRunTcs NodeRunCts { get; set; } - public Task CreateTimingTask(Action action, int time = 100, int count = -1) - { - NodeRunCts ??= ServiceContainer.Get(); - return Task.Factory.StartNew(async () => - { - for(int i = 0; i < count; i++) - { - NodeRunCts.Token.ThrowIfCancellationRequested(); - await time; - action.Invoke(); - } - }); - } - } - - public static class MyExtensions - { - public static TaskAwaiter GetAwaiter(this int i) => Task.Delay(i).GetAwaiter(); - } - - - // if (time <= 0) throw new ArgumentException("时间不能≤0"); -} diff --git a/Library.Core/Flow/MethodDetails.cs b/Library.Core/Flow/MethodDetails.cs deleted file mode 100644 index dd62b99..0000000 --- a/Library.Core/Flow/MethodDetails.cs +++ /dev/null @@ -1,240 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static Dm.net.buffer.ByteArrayBuffer; - -namespace Serein.Flow -{ - /// - /// 显式参数 - /// - public class ExplicitData - { - /// - /// 索引 - /// - public int Index { get; set; } - /// - /// 是否为显式参数 - /// - public bool IsExplicitData { get; set; } - /// - /// 显式类型 - /// - public Type? ExplicitType { get; set; } - - /// - /// 显示类型编号> - /// - public string ExplicitTypeName { get; set; } - - /// - /// 方法需要的类型 - /// - public Type DataType { get; set; } - - /// - /// 方法入参参数名称 - /// - public string ParameterName { get; set; } - - /// - /// 入参值 - /// - - public string DataValue { get; set; } - - - - public string[] Items { get; set; } - - - - - public ExplicitData Clone() => new() - { - Index = Index, - IsExplicitData = IsExplicitData, - ExplicitType = ExplicitType, - DataType = DataType, - ParameterName = ParameterName, - ExplicitTypeName = ExplicitTypeName, - DataValue = string.IsNullOrEmpty(DataValue) ? string.Empty : DataValue, - Items = [.. Items], - }; - } - - - - public class MethodDetails - { - public MethodDetails Clone() - { - return new MethodDetails - { - ActingInstance = ActingInstance, - ActingInstanceType = ActingInstanceType, - MethodDelegate = MethodDelegate, - MethodDynamicType = MethodDynamicType, - MethodGuid = Guid.NewGuid().ToString(), - MethodTips = MethodTips , - ReturnType = ReturnType, - MethodName = MethodName, - MethodLockName = MethodLockName, - - ExplicitDatas = ExplicitDatas.Select(it => it.Clone()).ToArray(), - }; - } - - /// - /// 作用实例 - /// - - public Type ActingInstanceType { get; set; } - - /// - /// 作用实例 - /// - - public object ActingInstance { get; set; } - - /// - /// 方法GUID - /// - - public string MethodGuid { get; set; } - - /// - /// 方法名称 - /// - - public string MethodName { get; set; } - - /// - /// 方法委托 - /// - - public Delegate MethodDelegate { get; set; } - - /// - /// 节点类型 - /// - public DynamicNodeType MethodDynamicType { get; set; } - /// - /// 锁名称 - /// - - public string MethodLockName { get; set; } - - - /// - /// 方法说明 - /// - - public string MethodTips { get; set; } - - - /// - /// 参数内容 - /// - - public ExplicitData[] ExplicitDatas { get; set; } - - - - /// - /// 出参类型 - /// - - public Type ReturnType { get; set; } - - - - - - - public bool IsCanConnect(Type returnType) - { - if (ExplicitDatas.Length == 0) - { - // 目标不需要传参,可以舍弃结果? - return true; - } - var types = ExplicitDatas.Select(it => it.DataType).ToArray(); - // 检查返回类型是否是元组类型 - if (returnType.IsGenericType && IsValueTuple(returnType)) - { - - return CompareGenericArguments(returnType, types); - } - else - { - int index = 0; - if (types[index] == typeof(DynamicContext)) - { - index++; - if (types.Length == 1) - { - return true; - } - } - // 被连接节点检查自己需要的参数类型,与发起连接的节点比较返回值类型 - if (returnType == types[index]) - { - return true; - } - } - return false; - } - - /// - /// 检查元组类型 - /// - /// - /// - private bool IsValueTuple(Type type) - { - if (!type.IsGenericType) return false; - - var genericTypeDef = type.GetGenericTypeDefinition(); - return genericTypeDef == typeof(ValueTuple<>) || - genericTypeDef == typeof(ValueTuple<,>) || - genericTypeDef == typeof(ValueTuple<,,>) || - genericTypeDef == typeof(ValueTuple<,,,>) || - genericTypeDef == typeof(ValueTuple<,,,,>) || - genericTypeDef == typeof(ValueTuple<,,,,,>) || - genericTypeDef == typeof(ValueTuple<,,,,,,>) || - genericTypeDef == typeof(ValueTuple<,,,,,,,>); - } - - private bool CompareGenericArguments(Type returnType, Type[] parameterTypes) - { - var genericArguments = returnType.GetGenericArguments(); - var length = parameterTypes.Length; - - for (int i = 0; i < genericArguments.Length; i++) - { - if (i >= length) return false; - - if (IsValueTuple(genericArguments[i])) - { - // 如果当前参数也是 ValueTuple,递归检查嵌套的泛型参数 - if (!CompareGenericArguments(genericArguments[i], parameterTypes.Skip(i).ToArray())) - { - return false; - } - } - else if (genericArguments[i] != parameterTypes[i]) - { - return false; - } - } - - return true; - } - } - - -} diff --git a/Library.Core/Flow/NodeFlowStarter.cs b/Library.Core/Flow/NodeFlowStarter.cs deleted file mode 100644 index 83cc335..0000000 --- a/Library.Core/Flow/NodeFlowStarter.cs +++ /dev/null @@ -1,171 +0,0 @@ -using Serein.Flow; -using Serein.Flow.NodeModel; -using Serein.Flow.Tool; -using Serein.Library.Http; -using Serein.Library.IOC; -using SqlSugar; - -namespace DynamicDemo.Node -{ - - public class NodeRunTcs: CancellationTokenSource - { - - } - - - public class NodeFlowStarter(IServiceContainer serviceContainer,List methodDetails) - - { - private readonly IServiceContainer ServiceContainer = serviceContainer; - private readonly List methodDetails = methodDetails; - - private Action ExitAction = null; - - - private DynamicContext context = null; - - - public NodeRunTcs MainCts; - - /// - /// 运行测试 - /// - /// - /// - //public async Task RunAsync1(List nodes) - //{ - // await Task.Run(async ()=> await StartRunAsync(nodes)); - //} - - public async Task RunAsync(List nodes) - { - var startNode = nodes.FirstOrDefault(p => p.IsStart); - if (startNode == null) { return; } - context = new(ServiceContainer); - - MainCts = ServiceContainer.CreateServiceInstance(); - - var initMethods = methodDetails.Where(it => it.MethodDynamicType == DynamicNodeType.Init).ToList(); - var loadingMethods = methodDetails.Where(it => it.MethodDynamicType == DynamicNodeType.Loading).ToList(); - var exitMethods = methodDetails.Where(it => it.MethodDynamicType == DynamicNodeType.Exit).ToList(); - ExitAction = () => - { - ServiceContainer.Run((web) => - { - web?.Stop(); - }); - foreach (MethodDetails? md in exitMethods) - { - object?[]? args = [context]; - object?[]? data = [md.ActingInstance, args]; - md.MethodDelegate.DynamicInvoke(data); - } - if(context != null && context.NodeRunCts != null && !context.NodeRunCts.IsCancellationRequested) - { - context.NodeRunCts.Cancel(); - } - if (MainCts!=null && !MainCts.IsCancellationRequested) MainCts.Cancel(); - ServiceContainer.Reset(); - }; - - - foreach (var md in initMethods) // 初始化 - 调用方法 - { - //md.ActingInstance = context.ServiceContainer.Get(md.ActingInstanceType); - object?[]? args = [context]; - object?[]? data = [md.ActingInstance, args]; - md.MethodDelegate.DynamicInvoke(data); - } - context.Biuld(); - - foreach (var md in loadingMethods) // 加载 - { - //md.ActingInstance = context.ServiceContainer.Get(md.ActingInstanceType); - object?[]? args = [context]; - object?[]? data = [md.ActingInstance, args]; - md.MethodDelegate.DynamicInvoke(data); - } - - var flipflopNodes = nodes.Where(it => it.MethodDetails?.MethodDynamicType == DynamicNodeType.Flipflop - && it.PreviousNodes.Count == 0 - && it.IsStart != true).ToArray(); - - var singleFlipflopNodes = flipflopNodes.Select(it => (SingleFlipflopNode)it).ToArray(); - - // 使用 TaskCompletionSource 创建未启动的任务 - var tasks = singleFlipflopNodes.Select(async node => - { - await FlipflopExecute(node); - }).ToArray(); - - - try - { - await Task.WhenAll([startNode.ExecuteStack(context),.. tasks]); - } - catch (Exception ex) - { - await Console.Out.WriteLineAsync(ex.ToString()); - } - - } - - private async Task FlipflopExecute(SingleFlipflopNode singleFlipFlopNode) - { - DynamicContext context = new DynamicContext(ServiceContainer); - MethodDetails md = singleFlipFlopNode.MethodDetails; - - try - { - - if (!DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - { - return; - } - - var func = md.ExplicitDatas.Length == 0 ? ((Func>)del) : ((Func>)del); - - while (!MainCts.IsCancellationRequested) // 循环中直到栈为空才会退出 - { - object?[]? parameters = singleFlipFlopNode.GetParameters(context, md); - // 调用委托并获取结果 - - FlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters); - - - if (flipflopContext == null) - { - break; - } - else if (flipflopContext.State == FfState.Cancel) - { - break; - } - else if (flipflopContext.State == FfState.Succeed) - { - singleFlipFlopNode.FlowState = true; - singleFlipFlopNode.FlowData = flipflopContext.Data; - var tasks = singleFlipFlopNode.SucceedBranch.Select(nextNode => - { - var context = new DynamicContext(ServiceContainer); - nextNode.PreviousNode = singleFlipFlopNode; - return nextNode.ExecuteStack(context); - }).ToArray(); - Task.WaitAll(tasks); - } - } - } - catch (Exception ex) - { - await Console.Out.WriteLineAsync(ex.ToString()); - } - } - - - public void Exit() - { - ExitAction?.Invoke(); - } - } -} diff --git a/Library.Core/Flow/NodeModel/CompositeActionNode.cs b/Library.Core/Flow/NodeModel/CompositeActionNode.cs deleted file mode 100644 index 96aadf1..0000000 --- a/Library.Core/Flow/NodeModel/CompositeActionNode.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace Serein.Flow.NodeModel -{ - - /// - /// 组合动作节点(用于动作区域) - /// - public class CompositeActionNode : NodeBase - { - public List ActionNodes; - /// - /// 组合动作节点(用于动作区域) - /// - public CompositeActionNode(List actionNodes) - { - ActionNodes = actionNodes; - } - public void AddNode(SingleActionNode node) - { - ActionNodes.Add(node); - MethodDetails ??= node.MethodDetails; - } - - //public override void Execute(DynamicContext context) - //{ - // //Dictionary dict = new Dictionary(); - // for (int i = 0; i < ActionNodes.Count; i++) - // { - // SingleActionNode? action = ActionNodes[i]; - // try - // { - // action.Execute(context); - // } - // catch (Exception ex) - // { - // Debug.Write(ex.Message); - // return; - // } - // } - - // CurrentState = true; - // return; - - - // /*foreach (var nextNode in TrueBranchNextNodes) - // { - // nextNode.ExecuteStack(context); - // }*/ - //} - } - -} diff --git a/Library.Core/Flow/NodeModel/CompositeConditionNode.cs b/Library.Core/Flow/NodeModel/CompositeConditionNode.cs deleted file mode 100644 index 2a21e6f..0000000 --- a/Library.Core/Flow/NodeModel/CompositeConditionNode.cs +++ /dev/null @@ -1,67 +0,0 @@ - -namespace Serein.Flow.NodeModel -{ - - /// - /// 组合条件节点(用于条件区域) - /// - public class CompositeConditionNode : NodeBase - { - public List ConditionNodes { get; } =[]; - - - public void AddNode(SingleConditionNode node) - { - ConditionNodes.Add(node); - MethodDetails ??= node.MethodDetails; - } - - public override object? Execute(DynamicContext context) - { - // bool allTrue = ConditionNodes.All(condition => Judge(context,condition.MethodDetails)); - // bool IsAllTrue = true; // 初始化为 true - FlowState = true; - foreach (SingleConditionNode? node in ConditionNodes) - { - if (!Judge(context, node)) - { - FlowState = false; - break;// 一旦发现条件为假,立即退出循环 - } - } - - return PreviousNode?.FlowData; - //if (IsAllTrue) - //{ - // foreach (var nextNode in TrueBranchNextNodes) - // { - // nextNode.ExecuteStack(context); - // } - //} - //else - //{ - // foreach (var nextNode in FalseBranchNextNodes) - // { - // nextNode.ExecuteStack(context); - // } - //} - } - private bool Judge(DynamicContext context, SingleConditionNode node) - { - try - { - node.Execute(context); - return node.FlowState; - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - return false; - } - - - - } - -} diff --git a/Library.Core/Flow/NodeModel/CompositeLoopNode.cs b/Library.Core/Flow/NodeModel/CompositeLoopNode.cs deleted file mode 100644 index ff1d8f3..0000000 --- a/Library.Core/Flow/NodeModel/CompositeLoopNode.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Serein.Flow.NodeModel -{ - public class CompositeLoopNode : NodeBase - { - } -} diff --git a/Library.Core/Flow/NodeModel/NodeBase.cs b/Library.Core/Flow/NodeModel/NodeBase.cs deleted file mode 100644 index 857ec9c..0000000 --- a/Library.Core/Flow/NodeModel/NodeBase.cs +++ /dev/null @@ -1,510 +0,0 @@ -using Newtonsoft.Json; -using Serein.Flow.Tool; - -namespace Serein.Flow.NodeModel -{ - - public enum ConnectionType - { - /// - /// 真分支 - /// - IsSucceed, - /// - /// 假分支 - /// - IsFail, - /// - /// 异常发生分支 - /// - IsError, - /// - /// 上游分支(执行当前节点前会执行一次上游分支) - /// - Upstream, - } - - /// - /// 节点基类(数据):条件控件,动作控件,条件区域,动作区域 - /// - public abstract class NodeBase : IDynamicFlowNode - { - - public MethodDetails MethodDetails { get; set; } - - - public string Guid { get; set; } - - - public string DisplayName { get; set; } - - public bool IsStart { get; set; } - - public string DelegateName { get; set; } - - - /// - /// 运行时的上一节点 - /// - public NodeBase? PreviousNode { get; set; } - - /// - /// 上一节点集合 - /// - public List PreviousNodes { get; set; } = []; - /// - /// 下一节点集合(真分支) - /// - public List SucceedBranch { get; set; } = []; - /// - /// 下一节点集合(假分支) - /// - public List FailBranch { get; set; } = []; - /// - /// 异常分支 - /// - public List ErrorBranch { get; set; } = []; - /// - /// 上游分支 - /// - public List UpstreamBranch { get; set; } = []; - - /// - /// 当前状态(进入真分支还是假分支,异常分支在异常中确定) - /// - public bool FlowState { get; set; } = true; - //public ConnectionType NextType { get; set; } = ConnectionType.IsTrue; - /// - /// 当前传递数据 - /// - public object? FlowData { get; set; } = null; - - - // 正常流程节点调用 - public virtual object? Execute(DynamicContext context) - { - MethodDetails md = MethodDetails; - object? result = null; - - if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - { - if (md.ExplicitDatas.Length == 0) - { - if (md.ReturnType == typeof(void)) - { - ((Action)del).Invoke(md.ActingInstance); - } - else - { - result = ((Func)del).Invoke(md.ActingInstance); - } - } - else - { - object?[]? parameters = GetParameters(context, MethodDetails); - if (md.ReturnType == typeof(void)) - { - ((Action)del).Invoke(md.ActingInstance, parameters); - } - else - { - result = ((Func)del).Invoke(md.ActingInstance, parameters); - - - } - } - // context.SetFlowData(result); - // CurrentData = result; - } - - return result; - } - - // 触发器调用 - public virtual async Task ExecuteAsync(DynamicContext context) - { - MethodDetails md = MethodDetails; - object? result = null; - - if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - { - if (md.ExplicitDatas.Length == 0) - { - // 调用委托并获取结果 - FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance); - - if (flipflopContext != null) - { - if (flipflopContext.State == FfState.Cancel) - { - throw new Exception("this async task is cancel."); - } - else - { - if (flipflopContext.State == FfState.Succeed) - { - FlowState = true; - result = flipflopContext.Data; - } - else - { - FlowState = false; - } - } - } - } - else - { - object?[]? parameters = GetParameters(context, MethodDetails); - // 调用委托并获取结果 - - - FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance, parameters); - - - - if (flipflopContext != null) - { - if (flipflopContext.State == FfState.Cancel) - { - throw new Exception("取消此异步"); - } - else - { - FlowState = flipflopContext.State == FfState.Succeed; - result = flipflopContext.Data; - } - } - } - } - - return result; - } - - public async Task ExecuteStack(DynamicContext context) - { - await Task.Run(async () => - { - await ExecuteStackTmp(context); - }); - } - - public async Task ExecuteStackTmp(DynamicContext context) - { - var cts = context.ServiceContainer.Get(); - - Stack stack =[]; - stack.Push(this); - - while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环 - { - // 从栈中弹出一个节点作为当前节点进行处理 - var currentNode = stack.Pop(); - - if (currentNode.MethodDetails != null) - { - currentNode.MethodDetails.ActingInstance ??= context.ServiceContainer.Get(MethodDetails.ActingInstanceType); - } // 设置方法执行的对象 - - // 获取上游分支,首先执行一次 - var upstreamNodes = currentNode.UpstreamBranch; - for (int i = upstreamNodes.Count - 1; i >= 0; i--) - { - upstreamNodes[i].PreviousNode = currentNode; - await upstreamNodes[i].ExecuteStack(context); - } - - - if (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == DynamicNodeType.Flipflop) - { - currentNode.FlowData = await currentNode.ExecuteAsync(context); - } - else - { - currentNode.FlowData = currentNode.Execute(context); - } - - - var nextNodes = currentNode.FlowState ? currentNode.SucceedBranch - : currentNode.FailBranch; - - // 将下一个节点集合中的所有节点逆序推入栈中 - for (int i = nextNodes.Count - 1; i >= 0; i--) - { - nextNodes[i].PreviousNode = currentNode; - stack.Push(nextNodes[i]); - } - } - } - - - public object[]? GetParameters(DynamicContext context, MethodDetails md) - { - // 用正确的大小初始化参数数组 - var types = md.ExplicitDatas.Select(it => it.DataType).ToArray(); - if (types.Length == 0) - { - return [md.ActingInstance]; - } - - object[]? parameters = new object[types.Length]; - - for (int i = 0; i < types.Length; i++) - { - - var mdEd = md.ExplicitDatas[i]; - Type type = mdEd.DataType; - - var f1 = PreviousNode?.FlowData?.GetType(); - var f2 = mdEd.DataType; - if (type == typeof(DynamicContext)) - { - parameters[i] = context; - } - else if (type == typeof(MethodDetails)) - { - parameters[i] = md; - } - else if (type == typeof(NodeBase)) - { - parameters[i] = this; - } - else if (mdEd.IsExplicitData) // 显式参数 - { - if (mdEd.DataType.IsEnum) - { - var enumValue = Enum.Parse(mdEd.DataType, mdEd.DataValue); - parameters[i] = enumValue; - } - else if (mdEd.ExplicitType == typeof(string)) - { - parameters[i] = mdEd.DataValue; - } - else if (mdEd.ExplicitType == typeof(bool)) - { - parameters[i] = bool.Parse(mdEd.DataValue); - } - else if (mdEd.ExplicitType == typeof(int)) - { - parameters[i] = int.Parse(mdEd.DataValue); - } - else if (mdEd.ExplicitType == typeof(double)) - { - parameters[i] = double.Parse(mdEd.DataValue); - } - else - { - parameters[i] = ""; - - //parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType); - } - } - else if ((f1 != null && f2 != null) && f2.IsAssignableFrom(f1) || f2.FullName.Equals(f1.FullName)) - { - parameters[i] = PreviousNode?.FlowData; - } - else - { - - - var tmpParameter = PreviousNode?.FlowData?.ToString(); - if (mdEd.DataType.IsEnum) - { - - var enumValue = Enum.Parse(mdEd.DataType, tmpParameter); - - parameters[i] = enumValue; - } - else if (mdEd.DataType == typeof(string)) - { - - parameters[i] = tmpParameter; - - } - else if (mdEd.DataType == typeof(bool)) - { - - parameters[i] = bool.Parse(tmpParameter); - - } - else if (mdEd.DataType == typeof(int)) - { - - parameters[i] = int.Parse(tmpParameter); - - } - else if (mdEd.DataType == typeof(double)) - { - - parameters[i] = double.Parse(tmpParameter); - - } - else - { - if (tmpParameter != null && mdEd.DataType!= null) - { - - parameters[i] = ConvertValue(tmpParameter, mdEd.DataType); - - } - } - } - - } - return parameters; - } - - - private dynamic? ConvertValue(string value, Type targetType) - { - try - { - if (!string.IsNullOrEmpty(value)) - { - return JsonConvert.DeserializeObject(value, targetType); - } - else - { - return null; - } - } - catch (JsonReaderException ex) - { - Console.WriteLine(ex); - return value; - } - catch (JsonSerializationException ex) - { - // 如果无法转为对应的JSON对象 - int startIndex = ex.Message.IndexOf("to type '") + "to type '".Length; // 查找类型信息开始的索引 - int endIndex = ex.Message.IndexOf('\''); // 查找类型信息结束的索引 - var typeInfo = ex.Message[startIndex..endIndex]; // 提取出错类型信息,该怎么传出去? - Console.WriteLine("无法转为对应的JSON对象:"+typeInfo); - return null; - } - catch // (Exception ex) - { - return value; - } - } - - - - - - #region 完整的ExecuteAsync调用方法(不要删除) - //public virtual async Task ExecuteAsync(DynamicContext context) - //{ - // MethodDetails md = MethodDetails; - // object? result = null; - // if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - // { - // if (md.ExplicitDatas.Length == 0) - // { - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance); - // } - // else if (md.ReturnType == typeof(Task)) - // { - // // 调用委托并获取结果 - // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance); - - // if (flipflopContext != null) - // { - // if (flipflopContext.State == FfState.Cancel) - // { - // throw new Exception("this async task is cancel."); - // } - // else - // { - // if (flipflopContext.State == FfState.Succeed) - // { - // CurrentState = true; - // result = flipflopContext.Data; - // } - // else - // { - // CurrentState = false; - // } - // } - // } - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance); - // } - // } - // else - // { - // object?[]? parameters = GetParameters(context, MethodDetails); - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance, parameters); - // } - // else if (md.ReturnType == typeof(Task)) - // { - // // 调用委托并获取结果 - // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance, parameters); - - // if (flipflopContext != null) - // { - // if (flipflopContext.State == FfState.Cancel) - // { - // throw new Exception("取消此异步"); - // } - // else - // { - // CurrentState = flipflopContext.State == FfState.Succeed; - // result = flipflopContext.Data; - // } - // } - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance, parameters); - // } - // } - // context.SetFlowData(result); - // } - // return result; - //} - #endregion - - - - - - - } - - -} - - -/* while (stack.Count > 0) // 循环中直到栈为空才会退出 - { - // 从栈中弹出一个节点作为当前节点进行处理 - var currentNode = stack.Pop(); - - if(currentNode is CompositeActionNode || currentNode is CompositeConditionNode) - { - currentNode.currentState = true; - } - else if (currentNode is CompositeConditionNode) - { - - } - currentNode.Execute(context); - // 根据当前节点的执行结果选择下一节点集合 - // 如果 currentState 为真,选择 TrueBranchNextNodes;否则选择 FalseBranchNextNodes - var nextNodes = currentNode.currentState ? currentNode.TrueBranchNextNodes - : currentNode.FalseBranchNextNodes; - - // 将下一个节点集合中的所有节点逆序推入栈中 - for (int i = nextNodes.Count - 1; i >= 0; i--) - { - stack.Push(nextNodes[i]); - } - - }*/ \ No newline at end of file diff --git a/Library.Core/Flow/NodeModel/SingleActionNode.cs b/Library.Core/Flow/NodeModel/SingleActionNode.cs deleted file mode 100644 index ec83725..0000000 --- a/Library.Core/Flow/NodeModel/SingleActionNode.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace Serein.Flow.NodeModel -{ - /// - /// 单动作节点(用于动作控件) - /// - public class SingleActionNode : NodeBase - { - //public override void Execute(DynamicContext context) - //{ - // try - // { - // Execute(context, base.MethodDetails); - // CurrentState = true; - // } - // catch (Exception ex) - // { - // Debug.Write(ex.Message); - // CurrentState = false; - // } - //} - - //public void Execute(DynamicContext context, MethodDetails md) - //{ - // if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - // { - - // object? result = null; - - // if (md.ExplicitDatas.Length == 0) - // { - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance); - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance); - // } - // } - // else - // { - // object?[]? parameters = GetParameters(context, MethodDetails); - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance, parameters); - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance, parameters); - // } - // } - - // // 根据 ExplicitDatas.Length 判断委托类型 - // //var action = (Action)del; - - // // 调用委托并获取结果 - // // action.Invoke(MethodDetails.ActingInstance, parameters); - - // //parameters = [md.ActingInstance, "", 123, ""]; - - // context.SetFlowData(result); - // } - //} - - } - - -} diff --git a/Library.Core/Flow/NodeModel/SingleConditionNode.cs b/Library.Core/Flow/NodeModel/SingleConditionNode.cs deleted file mode 100644 index 391634f..0000000 --- a/Library.Core/Flow/NodeModel/SingleConditionNode.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Serein.Flow.SerinExpression; - -namespace Serein.Flow.NodeModel -{ - /// - /// 条件节点(用于条件控件) - /// - public class SingleConditionNode : NodeBase - { - - /// - /// 是否为自定义参数 - /// - public bool IsCustomData { get; set; } - /// - /// 自定义参数值 - /// - public object? CustomData { get; set; } - /// - /// 条件表达式 - /// - - public string Expression { get; set; } - - - public override object? Execute(DynamicContext context) - { - // 接收上一节点参数or自定义参数内容 - object? result; - if (IsCustomData) - { - result = CustomData; - } - else - { - result = PreviousNode?.FlowData; - } - FlowState = SerinConditionParser.To(result, Expression); - Console.WriteLine($"{result} {Expression} -> " + FlowState); - return result; - } - - //public override void Execute(DynamicContext context) - //{ - // CurrentState = Judge(context, base.MethodDetails); - //} - - //private bool Judge(DynamicContext context, MethodDetails md) - //{ - // try - // { - // if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - // { - // object[] parameters = GetParameters(context, md); - // var temp = del.DynamicInvoke(parameters); - // //context.GetData(GetDyPreviousKey()); - // return (bool)temp; - // } - // } - // catch (Exception ex) - // { - // Debug.Write(ex.Message); - // } - // return false; - //} - - - } - - -} diff --git a/Library.Core/Flow/NodeModel/SingleExpOpNode.cs b/Library.Core/Flow/NodeModel/SingleExpOpNode.cs deleted file mode 100644 index f8811bc..0000000 --- a/Library.Core/Flow/NodeModel/SingleExpOpNode.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Serein.Flow.SerinExpression; - -namespace Serein.Flow.NodeModel -{ - /// - /// Expression Operation - 表达式操作 - /// - public class SingleExpOpNode : NodeBase - { - /// - /// 表达式 - /// - public string Expression { get; set; } - - - public override object? Execute(DynamicContext context) - { - var data = PreviousNode?.FlowData; - - var newData = SerinExpressionEvaluator.Evaluate(Expression, data, out bool isChange); - - FlowState = true; - Console.WriteLine(newData); - if (isChange) - { - return newData; - } - else - { - return PreviousNode?.FlowData; - } - - } - } -} diff --git a/Library.Core/Flow/NodeModel/SingleFlipflopNode.cs b/Library.Core/Flow/NodeModel/SingleFlipflopNode.cs deleted file mode 100644 index ace9fc2..0000000 --- a/Library.Core/Flow/NodeModel/SingleFlipflopNode.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Serein.Flow.NodeModel -{ - - public class SingleFlipflopNode : NodeBase - { - public override object Execute(DynamicContext context) - { - throw new NotImplementedException("无法以非await/async的形式调用触发器"); - } - - } -} diff --git a/Library.Core/Flow/SerinExpression/ConditionResolver.cs b/Library.Core/Flow/SerinExpression/ConditionResolver.cs deleted file mode 100644 index 126a960..0000000 --- a/Library.Core/Flow/SerinExpression/ConditionResolver.cs +++ /dev/null @@ -1,337 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace Serein.Flow.SerinExpression -{ - - public abstract class ConditionResolver - { - public abstract bool Evaluate(object obj); - } - - public class PassConditionResolver : ConditionResolver - { - public Operator Op { get; set; } - public override bool Evaluate(object obj) - { - return Op switch - { - Operator.Pass => true, - Operator.NotPass => false, - _ => throw new NotSupportedException("不支持的条件类型") - }; - } - - public enum Operator - { - Pass, - NotPass, - } - - } - - public class ValueTypeConditionResolver : ConditionResolver where T : struct, IComparable - { - public enum Operator - { - /// - /// 不进行任何操作 - /// - Node, - /// - /// 大于 - /// - GreaterThan, - /// - /// 小于 - /// - LessThan, - /// - /// 等于 - /// - Equal, - /// - /// 大于或等于 - /// - GreaterThanOrEqual, - /// - /// 小于或等于 - /// - LessThanOrEqual, - /// - /// 在两者之间 - /// - InRange, - /// - /// 不在两者之间 - /// - OutOfRange - } - - public Operator Op { get; set; } - public T Value { get; set; } - public T RangeStart { get; set; } - public T RangeEnd { get; set; } - - public string ArithmeticExpression { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is T typedObj) - { - double numericValue = Convert.ToDouble(typedObj); - if (!string.IsNullOrEmpty(ArithmeticExpression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(ArithmeticExpression, numericValue); - } - - T evaluatedValue = (T)Convert.ChangeType(numericValue, typeof(T)); - - return Op switch - { - Operator.GreaterThan => evaluatedValue.CompareTo(Value) > 0, - Operator.LessThan => evaluatedValue.CompareTo(Value) < 0, - Operator.Equal => evaluatedValue.CompareTo(Value) == 0, - Operator.GreaterThanOrEqual => evaluatedValue.CompareTo(Value) >= 0, - Operator.LessThanOrEqual => evaluatedValue.CompareTo(Value) <= 0, - Operator.InRange => evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0, - Operator.OutOfRange => evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0, - _ => throw new NotSupportedException("不支持的条件类型") - }; - /* switch (Op) - { - case Operator.GreaterThan: - return evaluatedValue.CompareTo(Value) > 0; - case Operator.LessThan: - return evaluatedValue.CompareTo(Value) < 0; - case Operator.Equal: - return evaluatedValue.CompareTo(Value) == 0; - case Operator.GreaterThanOrEqual: - return evaluatedValue.CompareTo(Value) >= 0; - case Operator.LessThanOrEqual: - return evaluatedValue.CompareTo(Value) <= 0; - case Operator.InRange: - return evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0; - case Operator.OutOfRange: - return evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0; - }*/ - } - return false; - } - } - - public class BoolConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 是 - /// - Is - } - - public Operator Op { get; set; } - public bool Value { get; set; } - - public override bool Evaluate(object obj) - { - - if (obj is bool boolObj) - { - return boolObj == Value; - /*switch (Op) - { - case Operator.Is: - return boolObj == Value; - }*/ - } - return false; - } - } - - public class StringConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 出现过 - /// - Contains, - /// - /// 没有出现过 - /// - DoesNotContain, - /// - /// 相等 - /// - Equal, - /// - /// 不相等 - /// - NotEqual, - /// - /// 起始字符串等于 - /// - StartsWith, - /// - /// 结束字符串等于 - /// - EndsWith - } - - public Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is string strObj) - { - return Op switch - { - Operator.Contains => strObj.Contains(Value), - Operator.DoesNotContain => !strObj.Contains(Value), - Operator.Equal => strObj == Value, - Operator.NotEqual => strObj != Value, - Operator.StartsWith => strObj.StartsWith(Value), - Operator.EndsWith => strObj.EndsWith(Value), - _ => throw new NotSupportedException("不支持的条件类型"), - }; - - /* switch (Op) - { - case Operator.Contains: - return strObj.Contains(Value); - case Operator.DoesNotContain: - return !strObj.Contains(Value); - case Operator.Equal: - return strObj == Value; - case Operator.NotEqual: - return strObj != Value; - case Operator.StartsWith: - return strObj.StartsWith(Value); - case Operator.EndsWith: - return strObj.EndsWith(Value); - }*/ - } - return false; - } - } - public class MemberConditionResolver : ConditionResolver where T : struct, IComparable - { - //public string MemberPath { get; set; } - public ValueTypeConditionResolver.Operator Op { get; set; } - public object? TargetObj { get; set; } - public T Value { get; set; } - - public string ArithmeticExpression { get; set; } - - public override bool Evaluate(object? obj) - { - //object? memberValue = GetMemberValue(obj, MemberPath); - if (TargetObj is T typedObj) - { - return new ValueTypeConditionResolver - { - Op = Op, - Value = Value, - ArithmeticExpression = ArithmeticExpression, - }.Evaluate(typedObj); - } - return false; - } - - //private object? GetMemberValue(object? obj, string memberPath) - //{ - // string[] members = memberPath[1..].Split('.'); - // foreach (var member in members) - // { - // if (obj == null) return null; - // Type type = obj.GetType(); - // PropertyInfo? propertyInfo = type.GetProperty(member); - // FieldInfo? fieldInfo = type.GetField(member); - // if (propertyInfo != null) - // obj = propertyInfo.GetValue(obj); - // else if (fieldInfo != null) - // obj = fieldInfo.GetValue(obj); - // else - // throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - // } - // return obj; - //} - } - - public class MemberStringConditionResolver : ConditionResolver - { - - public string MemberPath { get; set; } - - public StringConditionResolver.Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - object memberValue = GetMemberValue(obj, MemberPath); - if (memberValue is string strObj) - { - return new StringConditionResolver - { - Op = Op, - Value = Value - }.Evaluate(strObj); - } - return false; - } - - private object GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - - if (obj == null) return null; - - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - - return obj; - - } - - - - - - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - - - - - - } - -} diff --git a/Library.Core/Flow/SerinExpression/SerinConditionParser.cs b/Library.Core/Flow/SerinExpression/SerinConditionParser.cs deleted file mode 100644 index 64055b3..0000000 --- a/Library.Core/Flow/SerinExpression/SerinConditionParser.cs +++ /dev/null @@ -1,329 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Reflection; - -namespace Serein.Flow.SerinExpression; - -public class SerinConditionParser -{ - public static bool To(T data, string expression) - { - try - { - - return ConditionParse(data, expression).Evaluate(data); - - } - catch (Exception ex) - { - Console.WriteLine(ex); - throw; - } - } - - public static ConditionResolver ConditionParse(object data, string expression) - { - if (expression.StartsWith('.') /*&& expression.Contains('<') && expression.Contains('>')*/) - { - return ParseObjectExpression(data, expression); - } - else - { - return ParseSimpleExpression(data, expression); - } - - - bool ContainsArithmeticOperators(string expression) - { - return expression.Contains('+') || expression.Contains('-') || expression.Contains('*') || expression.Contains('/'); - } - - } - - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - private static object? GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - if (obj == null) return null; - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - return obj; - } - - private static ConditionResolver ParseObjectExpression(object data, string expression) - { - var parts = expression.Split(' '); - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - int typeStartIndex = expression.IndexOf('<'); - int typeEndIndex = expression.IndexOf('>'); - - string memberPath; - Type type; - object? targetObj; - if ((typeStartIndex + typeStartIndex) == -2) - { - memberPath = operatorStr; - targetObj = GetMemberValue(data, operatorStr); - - type = targetObj.GetType(); - - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - if (typeStartIndex >= typeEndIndex) - { - throw new ArgumentException("无效的表达式格式"); - } - memberPath = expression.Substring(0, typeStartIndex).Trim(); - string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1).Trim().ToLower(); - parts = expression.Substring(typeEndIndex + 1).Trim().Split(' '); - if (parts.Length == 3) - { - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - operatorStr = parts[0].ToLower(); - valueStr = string.Join(' ', parts.Skip(1)); - } - targetObj = GetMemberValue(data, memberPath); - - Type? tempType = typeStr switch - { - "int" => typeof(int), - "double" => typeof(double), - "bool" => typeof(bool), - "string" => typeof(string), - _ => Type.GetType(typeStr) - }; - type = tempType ?? throw new ArgumentException("对象表达式无效的类型声明"); - } - - - - if (type == typeof(int)) - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - TargetObj = targetObj, - //MemberPath = memberPath, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - else if (type == typeof(bool)) - { - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = (ValueTypeConditionResolver.Operator)ParseBoolOperator(operatorStr) - }; - } - else if (type == typeof(string)) - { - return new MemberStringConditionResolver - { - MemberPath = memberPath, - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - private static ConditionResolver ParseSimpleExpression(object data, string expression) - { - if ("pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.Pass, - }; - } - else - { - if ("not pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - if ("!pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - } - - - var parts = expression.Split(' '); - - if (parts.Length < 2) - throw new ArgumentException("无效的表达式格式。"); - - //string typeStr = parts[0]; - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - Type type = data.GetType();//Type.GetType(typeStr); - if (type == typeof(int)) - { - var op = ParseValueTypeOperator(operatorStr); - if (op == ValueTypeConditionResolver.Operator.InRange || op == ValueTypeConditionResolver.Operator.OutOfRange) - { - var temp = valueStr.Split('-'); - if (temp.Length < 2) - throw new ArgumentException($"范围无效:{valueStr}。"); - int rangeStart = int.Parse(temp[0], CultureInfo.InvariantCulture); - int rangeEnd = int.Parse(temp[1], CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - RangeStart = rangeStart, - RangeEnd = rangeEnd, - ArithmeticExpression = GetArithmeticExpression(parts[0]), - }; - } - else - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(bool)) - { - bool value = bool.Parse(valueStr); - return new BoolConditionResolver - { - Op = ParseBoolOperator(operatorStr), - Value = value, - }; - } - else if (type == typeof(string)) - { - return new StringConditionResolver - { - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - - private static ValueTypeConditionResolver.Operator ParseValueTypeOperator(string operatorStr) where T : struct, IComparable - { - return operatorStr switch - { - ">" => ValueTypeConditionResolver.Operator.GreaterThan, - "<" => ValueTypeConditionResolver.Operator.LessThan, - "==" => ValueTypeConditionResolver.Operator.Equal, - ">=" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "≥" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "<=" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "≤" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "equals" => ValueTypeConditionResolver.Operator.Equal, - "in" => ValueTypeConditionResolver.Operator.InRange, - "!in" => ValueTypeConditionResolver.Operator.OutOfRange, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for value type.") - }; - } - - private static BoolConditionResolver.Operator ParseBoolOperator(string operatorStr) - { - return operatorStr switch - { - "is" => BoolConditionResolver.Operator.Is, - "==" => BoolConditionResolver.Operator.Is, - "equals" => BoolConditionResolver.Operator.Is, - //"isFalse" => BoolConditionNode.Operator.IsFalse, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for bool type.") - }; - } - - private static StringConditionResolver.Operator ParseStringOperator(string operatorStr) - { - return operatorStr switch - { - "c" => StringConditionResolver.Operator.Contains, - "nc" => StringConditionResolver.Operator.DoesNotContain, - "sw" => StringConditionResolver.Operator.StartsWith, - "ew" => StringConditionResolver.Operator.EndsWith, - - "contains" => StringConditionResolver.Operator.Contains, - "doesNotContain" => StringConditionResolver.Operator.DoesNotContain, - "equals" => StringConditionResolver.Operator.Equal, - "==" => StringConditionResolver.Operator.Equal, - "notEquals" => StringConditionResolver.Operator.NotEqual, - "!=" => StringConditionResolver.Operator.NotEqual, - "startsWith" => StringConditionResolver.Operator.StartsWith, - "endsWith" => StringConditionResolver.Operator.EndsWith, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for string type.") - }; - } -} diff --git a/Library.Core/Flow/SerinExpression/SerinExpressionEvaluator.cs b/Library.Core/Flow/SerinExpression/SerinExpressionEvaluator.cs deleted file mode 100644 index 0992665..0000000 --- a/Library.Core/Flow/SerinExpression/SerinExpressionEvaluator.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static Serein.Flow.NodeModel.SingleExpOpNode; -using static System.Runtime.InteropServices.JavaScript.JSType; - -namespace Serein.Flow.SerinExpression -{ - public class SerinArithmeticExpressionEvaluator - { - private static readonly DataTable table = new DataTable(); - - public static double Evaluate(string expression, double inputValue) - { - // 替换占位符@为输入值 - expression = expression.Replace("@", inputValue.ToString()); - try - { - // 使用 DataTable.Compute 方法计算表达式 - var result = table.Compute(expression, string.Empty); - return Convert.ToDouble(result); - } - catch - { - throw new ArgumentException("Invalid arithmetic expression."); - } - } - } - - public class SerinExpressionEvaluator - { - public static object Evaluate(string expression, object targetObJ,out bool IsChange) - { - var parts = expression.Split([' '], 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid expression format."); - } - - var operation = parts[0].ToLower(); - var operand = parts[1][0] == '.' ? parts[1][1..]: parts[1]; - - var result = operation switch - { - "@num" => ComputedNumber(targetObJ, operand), - "@call" => InvokeMethod(targetObJ, operand), - "@get" => GetMember(targetObJ, operand), - "@set" => SetMember(targetObJ, operand), - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - IsChange = operation switch - { - "@num" => true, - "@call" => true, - "@get" => true, - "@set" => false, - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - return result; - } - - - private static readonly char[] separator = ['(', ')']; - private static readonly char[] separatorArray = [',']; - - private static object InvokeMethod(object target, string methodCall) - { - var methodParts = methodCall.Split(separator, StringSplitOptions.RemoveEmptyEntries); - if (methodParts.Length != 2) - { - throw new ArgumentException("Invalid method call format."); - } - - var methodName = methodParts[0]; - var parameterList = methodParts[1]; - var parameters = parameterList.Split(separatorArray, StringSplitOptions.RemoveEmptyEntries) - .Select(p => p.Trim()) - .ToArray(); - - var method = target.GetType().GetMethod(methodName); - if (method == null) - { - throw new ArgumentException($"Method {methodName} not found on target."); - } - - var parameterValues = method.GetParameters() - .Select((p, index) => Convert.ChangeType(parameters[index], p.ParameterType)) - .ToArray(); - - - return method.Invoke(target, parameterValues); - - } - - private static object GetMember(object target, string memberPath) - { - var members = memberPath.Split('.'); - foreach (var member in members) - { - - if (target == null) return null; - - - var property = target.GetType().GetProperty(member); - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - - return target; - - } - - private static object SetMember(object target, string assignment) - { - var parts = assignment.Split(new[] { '=' }, 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid assignment format."); - } - - var memberPath = parts[0].Trim(); - var value = parts[1].Trim(); - - var members = memberPath.Split('.'); - for (int i = 0; i < members.Length - 1; i++) - { - var member = members[i]; - - var property = target.GetType().GetProperty(member); - - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - var lastMember = members.Last(); - - var lastProperty = target.GetType().GetProperty(lastMember); - - if (lastProperty != null) - { - var convertedValue = Convert.ChangeType(value, lastProperty.PropertyType); - lastProperty.SetValue(target, convertedValue); - } - else - { - var lastField = target.GetType().GetField(lastMember); - if (lastField != null) - { - var convertedValue = Convert.ChangeType(value, lastField.FieldType); - lastField.SetValue(target, convertedValue); - } - else - { - throw new ArgumentException($"Member {lastMember} not found on target."); - } - } - - return target; - } - - private static double ComputedNumber(object value,string expression) - { - double numericValue = Convert.ToDouble(value); - if (!string.IsNullOrEmpty(expression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(expression, numericValue); - } - - return numericValue; - } - } -} diff --git a/Library.Core/Flow/Tool/DelegateGenerator.cs b/Library.Core/Flow/Tool/DelegateGenerator.cs deleted file mode 100644 index 47360ec..0000000 --- a/Library.Core/Flow/Tool/DelegateGenerator.cs +++ /dev/null @@ -1,192 +0,0 @@ -using Serein.Library.IOC; -using System.Collections.Concurrent; -using System.Reflection; - -namespace Serein.Flow.Tool; - - -public static class DelegateCache -{ - /// - /// 委托缓存全局字典 - /// - public static ConcurrentDictionary GlobalDicDelegates { get; } = new ConcurrentDictionary(); -} - -public static class DelegateGenerator -{ - // 缓存的实例对象(键:类型名称) - public static ConcurrentDictionary DynamicInstanceToType { get; } = new ConcurrentDictionary(); - // 缓存的实例对象 (键:生成的方法名称) - // public static ConcurrentDictionary DynamicInstance { get; } = new ConcurrentDictionary(); - - /// - /// 生成方法信息 - /// - /// - /// - /// - public static ConcurrentDictionary GenerateMethodDetails(IServiceContainer serviceContainer, Type type) - { - var methodDetailsDictionary = new ConcurrentDictionary(); - var assemblyName = type.Assembly.GetName().Name; - var methods = GetMethodsToProcess(type); - - foreach (var method in methods) - { - - var methodDetails = CreateMethodDetails(serviceContainer, type, method, assemblyName); - - methodDetailsDictionary.TryAdd(methodDetails.MethodName, methodDetails); - } - - return methodDetailsDictionary; - } - - /// - /// 获取处理方法 - /// - private static IEnumerable GetMethodsToProcess(Type type) - { - return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Where(m => m.GetCustomAttribute()?.Scan == true); - } - /// - /// 创建方法信息 - /// - /// - private static MethodDetails CreateMethodDetails(IServiceContainer serviceContainer, Type type, MethodInfo method, string assemblyName) - { - var methodName = method.Name; - var attribute = method.GetCustomAttribute(); - - var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters()); - // 生成委托 - var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型 - method, // 方法信息 - method.GetParameters(),// 方法参数 - method.ReturnType);// 返回值 - - - var dllTypeName = $"{assemblyName}.{type.Name}"; - serviceContainer.Register(type); - object instance = serviceContainer.GetOrCreateServiceInstance(type); - var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}"; - - - - return new MethodDetails - { - ActingInstanceType = type, - ActingInstance = instance, - MethodName = dllTypeMethodName, - MethodDelegate = methodDelegate, - MethodDynamicType = attribute.MethodDynamicType, - MethodLockName = attribute.LockName, - MethodTips = attribute.MethodTips, - ExplicitDatas = explicitDataOfParameters, - ReturnType = method.ReturnType, - }; - - } - - private static ExplicitData[] GetExplicitDataOfParameters(ParameterInfo[] parameters) - { - - return parameters.Select((it, index) => - { - //Console.WriteLine($"{it.Name}-{it.HasDefaultValue}-{it.DefaultValue}"); - string explicitTypeName = GetExplicitTypeName(it.ParameterType); - var items = GetExplicitItems(it.ParameterType, explicitTypeName); - if ("Bool".Equals(explicitTypeName)) explicitTypeName = "Select"; // 布尔值 转为 可选类型 - - - - return new ExplicitData - { - IsExplicitData = it.GetCustomAttribute(typeof(ExplicitAttribute)) is ExplicitAttribute, - Index = index, - ExplicitType = it.ParameterType, - ExplicitTypeName = explicitTypeName, - DataType = it.ParameterType, - ParameterName = it.Name, - DataValue = it.HasDefaultValue ? it.DefaultValue.ToString() : "", - Items = items.ToArray(), - }; - - - - }).ToArray(); - } - - private static string GetExplicitTypeName(Type type) - { - return type switch - { - Type t when t.IsEnum => "Select", - Type t when t == typeof(bool) => "Bool", - Type t when t == typeof(string) => "Value", - Type t when t == typeof(int) => "Value", - Type t when t == typeof(double) => "Value", - _ => "Value" - }; - } - - private static IEnumerable GetExplicitItems(Type type, string explicitTypeName) - { - return explicitTypeName switch - { - "Select" => Enum.GetNames(type), - "Bool" => ["True", "False"], - _ => [] - }; - - } - - private static Delegate GenerateMethodDelegate(Type type, MethodInfo methodInfo, ParameterInfo[] parameters, Type returnType) - { - var parameterTypes = parameters.Select(p => p.ParameterType).ToArray(); - var parameterCount = parameters.Length; - - if (returnType == typeof(void)) - { - if (parameterCount == 0) - { - // 无返回值,无参数 - return ExpressionHelper.MethodCaller(type, methodInfo); - } - else - { - // 无返回值,有参数 - return ExpressionHelper.MethodCaller(type, methodInfo, parameterTypes); - } - } - else if (returnType == typeof(Task)) // 触发器 - { - if (parameterCount == 0) - { - // 有返回值,无参数 - return ExpressionHelper.MethodCallerAsync(type, methodInfo); - } - else - { - // 有返回值,有参数 - return ExpressionHelper.MethodCallerAsync(type, methodInfo, parameterTypes); - } - } - else - { - if (parameterCount == 0) - { - // 有返回值,无参数 - return ExpressionHelper.MethodCallerHaveResult(type, methodInfo); - } - else - { - // 有返回值,有参数 - return ExpressionHelper.MethodCallerHaveResult(type, methodInfo, parameterTypes); - } - } - } - -} diff --git a/Library.Core/Flow/Tool/DynamicTool.cs b/Library.Core/Flow/Tool/DynamicTool.cs deleted file mode 100644 index a5d5c20..0000000 --- a/Library.Core/Flow/Tool/DynamicTool.cs +++ /dev/null @@ -1,194 +0,0 @@ -namespace Serein.Flow.Tool -{ - - #region 锁、tsk工具 (已注释) - /*public class LockManager - { - private readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); - - public void CreateLock(string name) - { - _locks.TryAdd(name, new LockQueue()); - } - - public async Task AcquireLockAsync(string name, CancellationToken cancellationToken = default) - { - if (!_locks.ContainsKey(name)) - { - throw new ArgumentException($"Lock with name '{name}' does not exist."); - } - - var lockQueue = _locks[name]; - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - lock (lockQueue.Queue) - { - lockQueue.Queue.Enqueue(tcs); - if (lockQueue.Queue.Count == 1) - { - tcs.SetResult(true); - } - } - - await tcs.Task.ConfigureAwait(false); - - // 处理取消操作 - if (cancellationToken.CanBeCanceled) - { - cancellationToken.Register(() => - { - lock (lockQueue.Queue) - { - if (lockQueue.Queue.Contains(tcs)) - { - tcs.TrySetCanceled(); - } - } - }); - } - } - - public void ReleaseLock(string name) - { - if (!_locks.ContainsKey(name)) - { - throw new ArgumentException($"Lock with name '{name}' does not exist."); - } - - var lockQueue = _locks[name]; - - lock (lockQueue.Queue) - { - if (lockQueue.Queue.Count > 0) - { - lockQueue.Queue.Dequeue(); - - if (lockQueue.Queue.Count > 0) - { - var next = lockQueue.Queue.Peek(); - next.SetResult(true); - } - } - } - } - - private class LockQueue - { - public Queue> Queue { get; } = new Queue>(); - } - } - - - public interface ITaskResult - { - object Result { get; } - } - - public class TaskResult : ITaskResult - { - public TaskResult(T result) - { - Result = result; - } - - public T Result { get; } - - object ITaskResult.Result => Result; - } - - public class DynamicTasks - { - private static readonly ConcurrentDictionary> TaskGuidPairs = new(); - public static Task GetTask(string Guid) - { - TaskGuidPairs.TryGetValue(Guid, out Task task); - return task; - } - - public static bool AddTask(string Guid, T result) - { - var task = Task.FromResult(new TaskResult(result)); - - return TaskGuidPairs.TryAdd(Guid, task); - } - } - public class TaskNodeManager - { - private readonly ConcurrentDictionary _taskQueues = new ConcurrentDictionary(); - - public void CreateTaskNode(string name) - { - _taskQueues.TryAdd(name, new TaskQueue()); - } - - public async Task WaitForTaskNodeAsync(string name, CancellationToken cancellationToken = default) - { - if (!_taskQueues.ContainsKey(name)) - { - throw new ArgumentException($"Task node with name '{name}' does not exist."); - } - - var taskQueue = _taskQueues[name]; - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - lock (taskQueue.Queue) - { - taskQueue.Queue.Enqueue(tcs); - if (taskQueue.Queue.Count == 1) - { - tcs.SetResult(true); - } - } - - await tcs.Task.ConfigureAwait(false); - - // 处理取消操作 - if (cancellationToken.CanBeCanceled) - { - cancellationToken.Register(() => - { - lock (taskQueue.Queue) - { - if (taskQueue.Queue.Contains(tcs)) - { - tcs.TrySetCanceled(); - } - } - }); - } - } - - public void CompleteTaskNode(string name) - { - if (!_taskQueues.ContainsKey(name)) - { - throw new ArgumentException($"Task node with name '{name}' does not exist."); - } - - var taskQueue = _taskQueues[name]; - - lock (taskQueue.Queue) - { - if (taskQueue.Queue.Count > 0) - { - taskQueue.Queue.Dequeue(); - - if (taskQueue.Queue.Count > 0) - { - var next = taskQueue.Queue.Peek(); - next.SetResult(true); - } - } - } - } - - private class TaskQueue - { - public Queue> Queue { get; } = new Queue>(); - } - }*/ - #endregion - - - -} diff --git a/Library.Core/Flow/Tool/ExpressionHelper.cs b/Library.Core/Flow/Tool/ExpressionHelper.cs deleted file mode 100644 index 16573b3..0000000 --- a/Library.Core/Flow/Tool/ExpressionHelper.cs +++ /dev/null @@ -1,740 +0,0 @@ -using System.Collections.Concurrent; -using System.Linq.Expressions; -using System.Reflection; - -namespace Serein.Flow.Tool -{ - /// - /// 对于实例创建的表达式树反射 - /// - public static class ExpressionHelper - { - /// - /// 缓存表达式树反射方法 - /// - private static ConcurrentDictionary Cache { get; } = new ConcurrentDictionary(); - - public static List GetCacheKey() - { - return [.. Cache.Keys]; - } - - #region 基于类型的表达式反射构建委托 - - #region 属性、字段的委托创建(表达式反射) - - /// - /// 动态获取属性值 - /// - public static Delegate PropertyGetter(Type type, string propertyName) - { - string cacheKey = $"{type.FullName}.{propertyName}.Getter"; - return Cache.GetOrAdd(cacheKey, _ => CreateGetterDelegate(type, propertyName)); - } - /// - /// 动态获取属性值 - /// - private static Delegate CreateGetterDelegate(Type type, string propertyName) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var property = Expression.Property(Expression.Convert(parameter, type), propertyName); - var lambda = Expression.Lambda(Expression.Convert(property, typeof(object)), parameter); - return lambda.Compile(); - } - - /// - /// 动态设置属性值 - /// - public static Delegate PropertySetter(Type type, string propertyName) - { - string cacheKey = $"{type.FullName}.{propertyName}.Setter"; - return Cache.GetOrAdd(cacheKey, _ => CreateSetterDelegate(type, propertyName)); - } - - /// - /// 动态设置属性值 - /// - private static Delegate CreateSetterDelegate(Type type, string propertyName) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var value = Expression.Parameter(typeof(object), "value"); - var property = Expression.Property(Expression.Convert(parameter, type), propertyName); - var assign = Expression.Assign(property, Expression.Convert(value, property.Type)); - var lambda = Expression.Lambda(assign, parameter, value); - return lambda.Compile(); - } - - /// - /// 动态获取字段值 - /// - public static Delegate FieldGetter(Type type, string fieldName) - { - string cacheKey = $"{type.FullName}.{fieldName}.FieldGetter"; - return Cache.GetOrAdd(cacheKey, _ => CreateFieldGetterDelegate(type, fieldName)); - } - /// - /// 动态获取字段值 - /// - private static Delegate CreateFieldGetterDelegate(Type type, string fieldName) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var field = Expression.Field(Expression.Convert(parameter, type), fieldName); - var lambda = Expression.Lambda(Expression.Convert(field, typeof(object)), parameter); - return lambda.Compile(); - } - - /// - /// 动态设置字段值 - /// - public static Delegate FieldSetter(Type type, string fieldName) - { - string cacheKey = $"{type.FullName}.{fieldName}.FieldSetter"; - return Cache.GetOrAdd(cacheKey, _ => CreateFieldSetterDelegate(type, fieldName)); - } - /// - /// 动态设置字段值 - /// - private static Delegate CreateFieldSetterDelegate(Type type, string fieldName) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var value = Expression.Parameter(typeof(object), "value"); - var field = Expression.Field(Expression.Convert(parameter, type), fieldName); - var assign = Expression.Assign(field, Expression.Convert(value, field.Type)); - var lambda = Expression.Lambda(assign, parameter, value); - return lambda.Compile(); - } - - #endregion - - - - /// - /// 表达式树构建无参数,无返回值方法 - /// - public static Delegate MethodCaller(Type type, MethodInfo methodInfo) - { - string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCaller"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(type, methodInfo)); - } - - /// - /// 表达式树构建无参数,无返回值方法 - /// - private static Delegate CreateMethodCallerDelegate(Type type, MethodInfo methodInfo) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var methodCall = Expression.Call(Expression.Convert(parameter, type), methodInfo); - var lambda = Expression.Lambda(methodCall, parameter); - // Action - return lambda.Compile(); - } - - /// - /// 表达式树构建无参数,有返回值方法 - /// - public static Delegate MethodCallerHaveResult(Type type, MethodInfo methodInfo) - { - string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCallerHaveResult"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateHaveResult(type, methodInfo)); - } - /// - /// 表达式树构建无参数,有返回值方法 - /// - private static Delegate CreateMethodCallerDelegateHaveResult(Type type, MethodInfo methodInfo) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var methodCall = Expression.Call(Expression.Convert(parameter, type), methodInfo); - var lambda = Expression.Lambda(Expression.Convert(methodCall, typeof(object)), parameter); - // Func - return lambda.Compile(); - } - - - /// - /// 表达式树构建多个参数,无返回值的方法 - /// - public static Delegate MethodCaller(Type type, MethodInfo methodInfo, params Type[] parameterTypes) - { - string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCaller"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(type, methodInfo, parameterTypes)); - } - - /// - /// 表达式树构建多个参数,无返回值的方法 - /// - private static Delegate CreateMethodCallerDelegate(Type type, MethodInfo methodInfo, Type[] parameterTypes) - { - /* var parameter = Expression.Parameter(typeof(object), "instance"); - - var arguments = parameterTypes.Select((t, i) => Expression.Parameter(typeof(object), $"arg{i}")).ToArray(); - - var convertedArguments = arguments.Select((arg, i) => Expression.Convert(arg, parameterTypes[i])).ToArray(); - var methodCall = Expression.Call(Expression.Convert(parameter, type), - methodInfo, - convertedArguments); - var lambda = Expression.Lambda(methodCall, new[] { parameter }.Concat(arguments)); - var tmpAction = lambda.Compile(); - - // Action - return lambda.Compile();*/ - - var instanceParam = Expression.Parameter(typeof(object), "instance"); - var argsParam = Expression.Parameter(typeof(object[]), "args"); - - // 创建参数表达式 - var convertedArgs = parameterTypes.Select((paramType, index) => - Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType) - ).ToArray(); - - - // 创建方法调用表达式 - var methodCall = Expression.Call( - Expression.Convert(instanceParam, type), - methodInfo, - (Expression[])convertedArgs - ); - - // 创建 lambda 表达式 - var lambda = Expression.Lambda( - methodCall, - instanceParam, - argsParam - ); - - // Func - return lambda.Compile(); - } - - /// - /// 表达式树构建多个参数,有返回值的方法 - /// - public static Delegate MethodCallerHaveResult(Type type, MethodInfo methodInfo, Type[] parameterTypes) - { - string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCallerHaveResult"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateHaveResult(type, methodInfo, parameterTypes)); - } - /// - /// 表达式树构建多个参数,有返回值的方法 - /// - private static Delegate CreateMethodCallerDelegateHaveResult(Type type, MethodInfo methodInfo, Type[] parameterTypes) - { - /*var instanceParam = Expression.Parameter(typeof(object), "instance"); - var argsParam = Expression.Parameter(typeof(object[]), "args"); - - // 创建参数表达式 - var convertedArgs = parameterTypes.Select((paramType, index) => - Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType) - ).ToArray(); - - - // 创建方法调用表达式 - var methodCall = Expression.Call( - Expression.Convert(instanceParam, type), - methodInfo, - convertedArgs - ); - - // 创建 lambda 表达式 - var lambda = Expression.Lambda( - Expression.Convert(methodCall, typeof(object)), - instanceParam, - argsParam - ); - - // Func - return lambda.Compile();*/ - - var instanceParam = Expression.Parameter(typeof(object), "instance"); - var argsParam = Expression.Parameter(typeof(object[]), "args"); - - // 创建参数表达式 - var convertedArgs = parameterTypes.Select((paramType, index) => - Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType) - ).ToArray(); - - - // 创建方法调用表达式 - var methodCall = Expression.Call( - Expression.Convert(instanceParam, type), - methodInfo, - convertedArgs - ); - - // 创建 lambda 表达式 - var lambda = Expression.Lambda>( - Expression.Convert(methodCall, typeof(object)), - instanceParam, - argsParam - ); - //var resule = task.DynamicInvoke((object)[Activator.CreateInstance(type), [new DynamicContext(null)]]); - return lambda.Compile(); - } - - - /// - /// 表达式树构建无参数,有返回值(Task)的方法(触发器) - /// - public static Delegate MethodCallerAsync(Type type, MethodInfo methodInfo) - { - string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCallerAsync"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateAsync(type, methodInfo)); - } - /// - /// 表达式树构建无参数,有返回值(Task)的方法(触发器) - /// - private static Delegate CreateMethodCallerDelegateAsync(Type type, MethodInfo methodInfo) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var methodCall = Expression.Call(Expression.Convert(parameter, type), methodInfo); - var lambda = Expression.Lambda>>( - Expression.Convert(methodCall, typeof(Task)), parameter); - // Func> - return lambda.Compile(); - } - - - - /// - /// 表达式树构建多个参数,有返回值(Task-object)的方法(触发器) - /// - public static Delegate MethodCallerAsync(Type type, MethodInfo method, params Type[] parameterTypes) - { - - string cacheKey = $"{type.FullName}.{method.Name}.MethodCallerAsync"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateAsync(type, method, parameterTypes)); - } - /// - /// 表达式树构建多个参数,有返回值(Task)的方法(触发器) - /// - private static Delegate CreateMethodCallerDelegateAsync(Type type, MethodInfo methodInfo, Type[] parameterTypes) - { - var instanceParam = Expression.Parameter(typeof(object), "instance"); - var argsParam = Expression.Parameter(typeof(object[]), "args"); - - // 创建参数表达式 - var convertedArgs = parameterTypes.Select((paramType, index) => - Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)),paramType) - ).ToArray(); - - - // 创建方法调用表达式 - var methodCall = Expression.Call( - Expression.Convert(instanceParam, type), - methodInfo, - (Expression[])convertedArgs - ); - - // 创建 lambda 表达式 - var lambda = Expression.Lambda>>( - Expression.Convert(methodCall, typeof(Task)), - instanceParam, - argsParam - ); - //var resule = task.DynamicInvoke((object)[Activator.CreateInstance(type), [new DynamicContext(null)]]); - return lambda.Compile(); - } - - - - #region 单参数 - - /// - /// 表达式树构建单参数,无返回值的方法 - /// - public static Delegate MethodCaller(Type type, string methodName, Type parameterType) - { - string cacheKey = $"{type.FullName}.{methodName}.MethodCallerWithParam"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(type, methodName, parameterType)); - } - /// - /// 表达式树构建单参数,无返回值的方法 - /// - private static Delegate CreateMethodCallerDelegate(Type type, string methodName, Type parameterType) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var argument = Expression.Parameter(typeof(object), "argument"); - var methodCall = Expression.Call(Expression.Convert(parameter, type), - type.GetMethod(methodName, [parameterType])!, - Expression.Convert(argument, parameterType)); - var lambda = Expression.Lambda(methodCall, parameter, argument); - return lambda.Compile(); - } - - /// - /// 表达式树构建单参数,有返回值的方法 - /// - public static Delegate MethodCallerWithResult(Type type, string methodName, Type parameterType, Type returnType) - { - string cacheKey = $"{type.FullName}.{methodName}.MethodCallerWithResult"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateWithResult(type, methodName, parameterType, returnType)); - } - /// - /// 表达式树构建单参数,有返回值的方法 - /// - private static Delegate CreateMethodCallerDelegateWithResult(Type type, string methodName, Type parameterType, Type returnType) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var argument = Expression.Parameter(typeof(object), "argument"); - var methodCall = Expression.Call(Expression.Convert(parameter, type), - type.GetMethod(methodName, [parameterType])!, - Expression.Convert(argument, parameterType)); - var lambda = Expression.Lambda(Expression.Convert(methodCall, typeof(object)), parameter, argument); - - - return lambda.Compile(); - } - - #endregion - - #endregion - - - #region 泛型表达式反射构建方法(已注释) - /* - - - /// - /// 动态获取属性值 - /// - /// - /// - /// - /// - public static Func PropertyGetter(string propertyName) - { - string cacheKey = $"{typeof(T).FullName}.{propertyName}.Getter"; - return (Func)Cache.GetOrAdd(cacheKey, _ => CreateGetterDelegate(propertyName)); - } - - private static Func CreateGetterDelegate(string propertyName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var property = Expression.Property(parameter, propertyName); - var lambda = Expression.Lambda>(property, parameter); - return lambda.Compile(); - } - - /// - /// 动态设置属性值 - /// - /// - /// - /// - /// - public static Action PropertySetter(string propertyName) - { - string cacheKey = $"{typeof(T).FullName}.{propertyName}.Setter"; - return (Action)Cache.GetOrAdd(cacheKey, _ => CreateSetterDelegate(propertyName)); - } - - private static Action CreateSetterDelegate(string propertyName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var value = Expression.Parameter(typeof(TProperty), "value"); - var property = Expression.Property(parameter, propertyName); - var assign = Expression.Assign(property, value); - var lambda = Expression.Lambda>(assign, parameter, value); - return lambda.Compile(); - } - - /// - /// 动态获取字段值 - /// - /// - /// - /// - /// - public static Func FieldGetter(string fieldName) - { - string cacheKey = $"{typeof(T).FullName}.{fieldName}.FieldGetter"; - return (Func)Cache.GetOrAdd(cacheKey, _ => CreateFieldGetterDelegate(fieldName)); - } - - private static Func CreateFieldGetterDelegate(string fieldName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var field = Expression.Field(parameter, fieldName); - var lambda = Expression.Lambda>(field, parameter); - return lambda.Compile(); - } - - /// - /// 动态设置字段值 - /// - /// - /// - /// - /// - public static Action FieldSetter(string fieldName) - { - string cacheKey = $"{typeof(T).FullName}.{fieldName}.FieldSetter"; - return (Action)Cache.GetOrAdd(cacheKey, _ => CreateFieldSetterDelegate(fieldName)); - } - - private static Action CreateFieldSetterDelegate(string fieldName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var value = Expression.Parameter(typeof(TField), "value"); - var field = Expression.Field(parameter, fieldName); - var assign = Expression.Assign(field, value); - var lambda = Expression.Lambda>(assign, parameter, value); - return lambda.Compile(); - } - - - - - - /// - /// 动态调用无参数方法 - /// - /// - /// - /// - public static Action MethodCaller(string methodName) - { - string cacheKey = $"{typeof(T).FullName}.{methodName}.MethodCaller"; - return (Action)Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(methodName)); - } - - private static Action CreateMethodCallerDelegate(string methodName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var methodCall = Expression.Call(parameter, typeof(T).GetMethod(methodName)); - var lambda = Expression.Lambda>(methodCall, parameter); - return lambda.Compile(); - } - - /// - /// 动态调用无参有返回值方法 - /// - /// - /// - /// - /// - public static Func MethodCallerHaveResul(string methodName) - { - string cacheKey = $"{typeof(T).FullName}.{methodName}.MethodCaller"; - return (Func)Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateHaveResult(methodName)); - } - - private static Func CreateMethodCallerDelegateHaveResult(string methodName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var methodCall = Expression.Call(parameter, typeof(T).GetMethod(methodName)); - var lambda = Expression.Lambda>(methodCall, parameter); - return lambda.Compile(); - } - - - /// - /// 动态调用单参数无返回值的方法 - /// - /// - /// - /// - /// - public static Action MethodCaller(string methodName) - { - string cacheKey = $"{typeof(T).FullName}.{methodName}.MethodCallerWithParam"; - return (Action)Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(methodName)); - } - - private static Action CreateMethodCallerDelegate(string methodName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var argument = Expression.Parameter(typeof(TParam), "argument"); - var methodCall = Expression.Call(parameter, typeof(T).GetMethod(methodName), argument); - var lambda = Expression.Lambda>(methodCall, parameter, argument); - return lambda.Compile(); - } - - /// - /// 动态调用单参数有返回值的方法 - /// - /// - /// - /// - /// - /// - public static Func MethodCallerWithResult(string methodName) - { - string cacheKey = $"{typeof(T).FullName}.{methodName}.MethodCallerWithResult"; - return (Func)Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(methodName)); - } - - private static Func CreateMethodCallerDelegate(string methodName) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var argument = Expression.Parameter(typeof(TParam), "argument"); - var methodCall = Expression.Call(parameter, typeof(T).GetMethod(methodName), argument); - var lambda = Expression.Lambda>(methodCall, parameter, argument); - return lambda.Compile(); - } - - /// - /// 动态调用多参无返回值的方法 - /// - /// - /// - /// - /// - public static Action MethodCaller(string methodName, params Type[] parameterTypes) - { - string cacheKey = $"{typeof(T).FullName}.{methodName}.MethodCaller"; - return (Action)Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(methodName, parameterTypes)); - } - - private static Action CreateMethodCallerDelegate(string methodName, Type[] parameterTypes) - { - var parameter = Expression.Parameter(typeof(T), "instance"); - var arguments = parameterTypes.Select((type, index) => - Expression.Parameter(typeof(object), $"arg{index}") - ).ToList(); - - var convertedArguments = arguments.Select((arg, index) => - Expression.Convert(arg, parameterTypes[index]) - ).ToList(); - - var methodInfo = typeof(T).GetMethod(methodName, parameterTypes); - - if (methodInfo == null) - { - throw new ArgumentException($"Method '{methodName}' not found in type '{typeof(T).FullName}' with given parameter types."); - } - - var methodCall = Expression.Call(parameter, methodInfo, convertedArguments); - var lambda = Expression.Lambda>(methodCall, new[] { parameter }.Concat(arguments)); - return lambda.Compile(); - } - - - - /// - /// 动态调用多参有返回值的方法 - /// - /// - /// - /// - /// - /// - public static Func MethodCallerHaveResult(string methodName, Type[] parameterTypes) - { - string cacheKey = $"{typeof(T).FullName}.{methodName}.MethodCallerHaveResult"; - return (Func)Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(methodName, parameterTypes)); - } - - private static Func CreateMethodCallerDelegate(string methodName, Type[] parameterTypes) - { - var instanceParam = Expression.Parameter(typeof(T), "instance"); - var argsParam = Expression.Parameter(typeof(object[]), "args"); - - var convertedArgs = new Expression[parameterTypes.Length]; - for (int i = 0; i < parameterTypes.Length; i++) - { - var index = Expression.Constant(i); - var argType = parameterTypes[i]; - var arrayIndex = Expression.ArrayIndex(argsParam, index); - var convertedArg = Expression.Convert(arrayIndex, argType); - convertedArgs[i] = convertedArg; - } - - var methodInfo = typeof(T).GetMethod(methodName, parameterTypes); - - if (methodInfo == null) - { - throw new ArgumentException($"Method '{methodName}' not found in type '{typeof(T).FullName}' with given parameter types."); - } - - var methodCall = Expression.Call(instanceParam, methodInfo, convertedArgs); - var lambda = Expression.Lambda>(methodCall, instanceParam, argsParam); - return lambda.Compile(); - } - - - - - - - - - */ - - #endregion - #region 暂时不删(已注释) - /* /// - /// 表达式树构建多个参数,有返回值的方法 - /// - public static Delegate MethodCallerHaveResult(Type type, string methodName, Type[] parameterTypes) - { - string cacheKey = $"{type.FullName}.{methodName}.MethodCallerHaveResult"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateHaveResult(type, methodName, parameterTypes)); - } - - private static Delegate CreateMethodCallerDelegateHaveResult(Type type, string methodName, Type[] parameterTypes) - { - var instanceParam = Expression.Parameter(typeof(object), "instance"); - var argsParam = Expression.Parameter(typeof(object[]), "args"); - var convertedArgs = parameterTypes.Select((paramType, index) => - Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType) - ).ToArray(); - var methodCall = Expression.Call(Expression.Convert(instanceParam, type), type.GetMethod(methodName, parameterTypes), convertedArgs); - var lambda = Expression.Lambda(Expression.Convert(methodCall, typeof(object)), instanceParam, argsParam); - return lambda.Compile(); - }*/ - - - - /*/// - /// 表达式反射 构建 无返回值、无参数 的委托 - /// - /// - /// - /// - /// - public static Delegate MethodCaller(Type type, string methodName, Type[] parameterTypes) - { - string cacheKey = $"{type.FullName}.{methodName}.{string.Join(",", parameterTypes.Select(t => t.FullName))}.MethodCaller"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(type, methodName, parameterTypes)); - } - - /// - /// 表达式反射 构建 无返回值、无参数 的委托 - /// - /// - /// - /// - /// - private static Delegate CreateMethodCallerDelegate(Type type, string methodName, Type[] parameterTypes) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var arguments = parameterTypes.Select((paramType, index) => Expression.Parameter(paramType, $"param{index}")).ToArray(); - var methodCall = Expression.Call(Expression.Convert(parameter, type), type.GetMethod(methodName, parameterTypes), arguments); - - var delegateType = Expression.GetActionType(new[] { typeof(object) }.Concat(parameterTypes).ToArray()); - var lambda = Expression.Lambda(delegateType, methodCall, new[] { parameter }.Concat(arguments).ToArray()); - return lambda.Compile(); - } -*/ - /*public static Delegate MethodCallerHaveResult(Type type, string methodName, Type returnType, Type[] parameterTypes) - { - string cacheKey = $"{type.FullName}.{methodName}.{string.Join(",", parameterTypes.Select(t => t.FullName))}.MethodCallerHaveResult"; - return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateHaveResult(type, methodName, returnType, parameterTypes)); - } - - private static Delegate CreateMethodCallerDelegateHaveResult(Type type, string methodName, Type returnType, Type[] parameterTypes) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var arguments = parameterTypes.Select((paramType, index) => Expression.Parameter(paramType, $"param{index}")).ToArray(); - var methodCall = Expression.Call(Expression.Convert(parameter, type), type.GetMethod(methodName, parameterTypes), arguments); - - var delegateType = Expression.GetFuncType(new[] { typeof(object) }.Concat(parameterTypes).Concat(new[] { typeof(object) }).ToArray()); - var lambda = Expression.Lambda(delegateType, Expression.Convert(methodCall, typeof(object)), new[] { parameter }.Concat(arguments).ToArray()); - return lambda.Compile(); - } - -*/ - - #endregion - } -} diff --git a/Library.Core/Flow/Tool/TcsSignal.cs b/Library.Core/Flow/Tool/TcsSignal.cs deleted file mode 100644 index cd6e3f4..0000000 --- a/Library.Core/Flow/Tool/TcsSignal.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Collections.Concurrent; - -namespace Serein.Flow.Tool -{ - public class TcsSignalException : Exception - { - public FfState FfState { get; set; } - public TcsSignalException(string? message) : base(message) - { - FfState = FfState.Cancel; - } - } - - public class TcsSignal where TSignal : struct, Enum - { - - public ConcurrentDictionary>> TcsEvent { get; } = new(); - - // public object tcsObj = new object(); - - public bool TriggerSignal(TSignal signal, T state) - { - if (TcsEvent.TryRemove(signal, out var waitTcss)) - { - while (waitTcss.Count > 0) - { - - waitTcss.Pop().SetResult(state); - - } - return true; - } - return false; - - - } - - public TaskCompletionSource CreateTcs(TSignal signal) - { - - var tcs = new TaskCompletionSource(); - TcsEvent.GetOrAdd(signal, _ => new Stack>()).Push(tcs); - return tcs; - - - - } - //public TaskCompletionSource GetOrCreateTcs(TSignal signal) - //{ - // lock (tcsObj) - // { - // var tcs = TcsEvent.GetOrAdd(signal, _ => new TaskCompletionSource()); - // if (tcs.Task.IsCompleted) - // { - // TcsEvent.TryRemove(signal, out _); - // tcs = new TaskCompletionSource(); - // TcsEvent[signal] = tcs; - // } - // return tcs; - // } - //} - - public void CancelTask() - { - lock(TcsEvent) - { - - foreach (var tcss in TcsEvent.Values) - { - while (tcss.Count > 0) - { - tcss.Pop().SetException(new TcsSignalException("Task Cancel")); - } - } - TcsEvent.Clear(); - } - } - - } -} diff --git a/Library.Core/IOC/SereinIoc.cs b/Library.Core/IOC/SereinIoc.cs deleted file mode 100644 index 63eea9a..0000000 --- a/Library.Core/IOC/SereinIoc.cs +++ /dev/null @@ -1,373 +0,0 @@ -using Serein.Library.Api; -using Serein.Library.Attributes; -using System.Collections.Concurrent; -using System.Reflection; - -namespace Serein.Library.Core.IOC -{ - public class SereinIoc : ISereinIoc - { - - private readonly ConcurrentDictionary _dependencies; - private readonly ConcurrentDictionary _typeMappings; - private readonly List _waitingForInstantiation; - - public SereinIoc() - { - - _dependencies = new ConcurrentDictionary - { - [typeof(ISereinIoc).FullName] = this - }; - - _typeMappings = new ConcurrentDictionary(); - _waitingForInstantiation = []; - } - public object GetOrCreateServiceInstance(Type type, params object[] parameters) - { - Register(type); - object instance; - - if (_dependencies.ContainsKey(type.FullName)) - { - instance = _dependencies[type.FullName]; - } - else - { - - instance = Activator.CreateInstance(type); - - - _dependencies[type.FullName] = instance; - - } - - - return instance; - } - public T CreateServiceInstance(params object[] parameters) - { - return (T)GetOrCreateServiceInstance(typeof(T), parameters); - } - - public ISereinIoc Reset() - { - foreach(var instancei in _dependencies.Values) - { - if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable) - { - disposable.Dispose(); - } - } - _dependencies.Clear(); - _waitingForInstantiation.Clear(); - //_typeMappings.Clear(); - return this; - } - - public ISereinIoc Register(Type type, params object[] parameters) - { - - if (!_typeMappings.ContainsKey(type.FullName)) - { - _typeMappings[type.FullName] = type; - } - - return this; - } - public ISereinIoc Register(params object[] parameters) - { - Register(typeof(T), parameters); - return this; - } - - public ISereinIoc Register(params object[] parameters) - where TImplementation : TService - { - _typeMappings[typeof(TService).FullName!] = typeof(TImplementation); - return this; - } - - public object GetOrInstantiate(Type type) - { - - - if (!_dependencies.TryGetValue(type.FullName, out object value)) - { - Register(type); - - value = Instantiate(type); - - InjectDependencies(type); - } - - - - return value; - - } - - - public T GetOrInstantiate() - { - if(!_dependencies.TryGetValue(typeof(T).FullName, out object value)) - { - Register(); - - value = Instantiate(typeof(T)); - } - - return (T)value; - //throw new InvalidOperationException("目标类型未创建实例"); - } - public ISereinIoc Build() - { - foreach (var type in _typeMappings.Values) - { - - if(!_dependencies.ContainsKey(type.FullName)) - { - - _dependencies[type.FullName] = Activator.CreateInstance(type); - - } - - } - - foreach (var instance in _dependencies.Values) - { - - InjectDependencies(instance); // 替换占位符 - } - - //var instance = Instantiate(item.Value); - - TryInstantiateWaitingDependencies(); - return this; - } - - public object? Instantiate(Type controllerType, params object[] parameters) - { - var instance = Activator.CreateInstance(controllerType, parameters); - if(instance != null) - { - InjectDependencies(instance); - } - return instance; - } - - private void InjectDependencies(object instance) - { - var properties = instance.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public) - .Where(p => p.CanWrite && p.GetCustomAttribute() != null); - - foreach (var property in properties) - { - var propertyType = property.PropertyType; - - if (_dependencies.TryGetValue(propertyType.FullName, out var dependencyInstance)) - { - property.SetValue(instance, dependencyInstance); - } - - } - } - - private void TryInstantiateWaitingDependencies() - { - foreach (var waitingType in _waitingForInstantiation.ToList()) - { - if (_typeMappings.TryGetValue(waitingType.FullName!, out var implementationType)) - { - var instance = Instantiate(implementationType); - if (instance != null) - { - - _dependencies[waitingType.FullName] = instance; - - _waitingForInstantiation.Remove(waitingType); - } - } - } - } - - #region run() - public ISereinIoc Run(Action action) - { - var service = GetOrInstantiate(); - if (service != null) - { - action(service); - } - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - - action(service1, service2); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - action(service1, service2, service3); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - action(service1, service2, service3, service4); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - var service6 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5, service6); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - var service6 = GetOrInstantiate(); - var service7 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5, service6, service7); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - var service6 = GetOrInstantiate(); - var service7 = GetOrInstantiate(); - var service8 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5, service6, service7, service8); - return this; - } - - #endregion - } - - - /* public interface IServiceContainer - { - ServiceContainer Register(params object[] parameters); - ServiceContainer Register(params object[] parameters) where TImplementation : TService; - TService Resolve(); - void Get(Action action); - object Instantiate(Type type, params object[] parameters); - - } - public class ServiceContainer : IServiceContainer - { - private readonly Dictionary _dependencies; - public ServiceContainer() - { - _dependencies = new Dictionary - { - [typeof(IServiceContainer)] = this - }; - } - - public void Get(Action action) - { - var service = Resolve(); - action(service); - } - public ServiceContainer Register(params object[] parameters) - { - var instance = Instantiate(typeof(T), parameters); - _dependencies[typeof(T)] = instance; - return this; - } - - public ServiceContainer Register(params object[] parameters) - where TImplementation : TService - { - - _dependencies[typeof(TService)] = Instantiate(typeof(TImplementation), parameters); - return this; - } - - - public TService Resolve() - { - return (TService)_dependencies[typeof(TService)]; - } - - public object Instantiate(Type controllerType, params object[] parameters) - { - var constructors = controllerType.GetConstructors(); // 获取控制器的所有构造函数 - - // 查找具有最多参数的构造函数 - var constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); - - if (constructor != null) - { - if (parameters.Length > 0) - { - return Activator.CreateInstance(controllerType, parameters); - } - else { - var tmpParameters = constructor.GetParameters(); - var dependencyInstances = new List(); - - foreach (var parameter in tmpParameters) - { - var parameterType = parameter.ParameterType; - _dependencies.TryGetValue(parameterType, out var dependencyInstance); - dependencyInstances.Add(dependencyInstance); - if (dependencyInstance == null) - { - return null; - } - } - // 用解析的依赖项实例化目标类型 - return Activator.CreateInstance(controllerType, dependencyInstances.ToArray()); - } - } - else - { - return Activator.CreateInstance(controllerType); - } - } - }*/ - - - -} diff --git a/Library.Core/SerinExpression/ConditionResolver.cs b/Library.Core/SerinExpression/ConditionResolver.cs deleted file mode 100644 index 0e13911..0000000 --- a/Library.Core/SerinExpression/ConditionResolver.cs +++ /dev/null @@ -1,337 +0,0 @@ -using System.Reflection; - -namespace Serein.LibraryCore.SerinExpression -{ - /// - /// 条件解析抽象类 - /// - public abstract class ConditionResolver - { - public abstract bool Evaluate(object obj); - } - - public class PassConditionResolver : ConditionResolver - { - public Operator Op { get; set; } - public override bool Evaluate(object obj) - { - return Op switch - { - Operator.Pass => true, - Operator.NotPass => false, - _ => throw new NotSupportedException("不支持的条件类型") - }; - } - - public enum Operator - { - Pass, - NotPass, - } - - } - - public class ValueTypeConditionResolver : ConditionResolver where T : struct, IComparable - { - public enum Operator - { - /// - /// 不进行任何操作 - /// - Node, - /// - /// 大于 - /// - GreaterThan, - /// - /// 小于 - /// - LessThan, - /// - /// 等于 - /// - Equal, - /// - /// 大于或等于 - /// - GreaterThanOrEqual, - /// - /// 小于或等于 - /// - LessThanOrEqual, - /// - /// 在两者之间 - /// - InRange, - /// - /// 不在两者之间 - /// - OutOfRange - } - - public Operator Op { get; set; } - public T Value { get; set; } - public T RangeStart { get; set; } - public T RangeEnd { get; set; } - - public string ArithmeticExpression { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is T typedObj) - { - double numericValue = Convert.ToDouble(typedObj); - if (!string.IsNullOrEmpty(ArithmeticExpression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(ArithmeticExpression, numericValue); - } - - T evaluatedValue = (T)Convert.ChangeType(numericValue, typeof(T)); - - return Op switch - { - Operator.GreaterThan => evaluatedValue.CompareTo(Value) > 0, - Operator.LessThan => evaluatedValue.CompareTo(Value) < 0, - Operator.Equal => evaluatedValue.CompareTo(Value) == 0, - Operator.GreaterThanOrEqual => evaluatedValue.CompareTo(Value) >= 0, - Operator.LessThanOrEqual => evaluatedValue.CompareTo(Value) <= 0, - Operator.InRange => evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0, - Operator.OutOfRange => evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0, - _ => throw new NotSupportedException("不支持的条件类型") - }; - /* switch (Op) - { - case Operator.GreaterThan: - return evaluatedValue.CompareTo(Value) > 0; - case Operator.LessThan: - return evaluatedValue.CompareTo(Value) < 0; - case Operator.Equal: - return evaluatedValue.CompareTo(Value) == 0; - case Operator.GreaterThanOrEqual: - return evaluatedValue.CompareTo(Value) >= 0; - case Operator.LessThanOrEqual: - return evaluatedValue.CompareTo(Value) <= 0; - case Operator.InRange: - return evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0; - case Operator.OutOfRange: - return evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0; - }*/ - } - return false; - } - } - - public class BoolConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 是 - /// - Is - } - - public Operator Op { get; set; } - public bool Value { get; set; } - - public override bool Evaluate(object obj) - { - - if (obj is bool boolObj) - { - return boolObj == Value; - /*switch (Op) - { - case Operator.Is: - return boolObj == Value; - }*/ - } - return false; - } - } - - public class StringConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 出现过 - /// - Contains, - /// - /// 没有出现过 - /// - DoesNotContain, - /// - /// 相等 - /// - Equal, - /// - /// 不相等 - /// - NotEqual, - /// - /// 起始字符串等于 - /// - StartsWith, - /// - /// 结束字符串等于 - /// - EndsWith - } - - public Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is string strObj) - { - return Op switch - { - Operator.Contains => strObj.Contains(Value), - Operator.DoesNotContain => !strObj.Contains(Value), - Operator.Equal => strObj == Value, - Operator.NotEqual => strObj != Value, - Operator.StartsWith => strObj.StartsWith(Value), - Operator.EndsWith => strObj.EndsWith(Value), - _ => throw new NotSupportedException("不支持的条件类型"), - }; - - /* switch (Op) - { - case Operator.Contains: - return strObj.Contains(Value); - case Operator.DoesNotContain: - return !strObj.Contains(Value); - case Operator.Equal: - return strObj == Value; - case Operator.NotEqual: - return strObj != Value; - case Operator.StartsWith: - return strObj.StartsWith(Value); - case Operator.EndsWith: - return strObj.EndsWith(Value); - }*/ - } - return false; - } - } - public class MemberConditionResolver : ConditionResolver where T : struct, IComparable - { - //public string MemberPath { get; set; } - public ValueTypeConditionResolver.Operator Op { get; set; } - public object? TargetObj { get; set; } - public T Value { get; set; } - - public string ArithmeticExpression { get; set; } - - public override bool Evaluate(object? obj) - { - //object? memberValue = GetMemberValue(obj, MemberPath); - if (TargetObj is T typedObj) - { - return new ValueTypeConditionResolver - { - Op = Op, - Value = Value, - ArithmeticExpression = ArithmeticExpression, - }.Evaluate(typedObj); - } - return false; - } - - //private object? GetMemberValue(object? obj, string memberPath) - //{ - // string[] members = memberPath[1..].Split('.'); - // foreach (var member in members) - // { - // if (obj == null) return null; - // Type type = obj.GetType(); - // PropertyInfo? propertyInfo = type.GetProperty(member); - // FieldInfo? fieldInfo = type.GetField(member); - // if (propertyInfo != null) - // obj = propertyInfo.GetValue(obj); - // else if (fieldInfo != null) - // obj = fieldInfo.GetValue(obj); - // else - // throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - // } - // return obj; - //} - } - - public class MemberStringConditionResolver : ConditionResolver - { - - public string MemberPath { get; set; } - - public StringConditionResolver.Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - object memberValue = GetMemberValue(obj, MemberPath); - if (memberValue is string strObj) - { - return new StringConditionResolver - { - Op = Op, - Value = Value - }.Evaluate(strObj); - } - return false; - } - - private object GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - - if (obj == null) return null; - - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - - return obj; - - } - - - - - - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - - - - - - } - -} diff --git a/Library.Core/SerinExpression/SerinConditionParser.cs b/Library.Core/SerinExpression/SerinConditionParser.cs deleted file mode 100644 index 3a57418..0000000 --- a/Library.Core/SerinExpression/SerinConditionParser.cs +++ /dev/null @@ -1,338 +0,0 @@ -using System.Globalization; -using System.Reflection; - -namespace Serein.LibraryCore.SerinExpression; - -public class SerinConditionParser -{ - public static bool To(T data, string expression) - { - try - { - - return ConditionParse(data, expression).Evaluate(data); - - } - catch (Exception ex) - { - Console.WriteLine(ex); - throw; - } - } - - public static ConditionResolver ConditionParse(object data, string expression) - { - if (expression.StartsWith('.')) // 表达式前缀属于从上一个节点数据对象获取成员值 - { - return ParseObjectExpression(data, expression); - } - else - { - return ParseSimpleExpression(data, expression); - } - - - //bool ContainsArithmeticOperators(string expression) - //{ - // return expression.Contains('+') || expression.Contains('-') || expression.Contains('*') || expression.Contains('/'); - //} - - } - - /// - /// 获取计算表达式的部分 - /// - /// - /// - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - /// - /// 获取对象指定名称的成员 - /// - private static object? GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - if (obj == null) return null; - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - return obj; - } - /// - /// 解析对象表达式 - /// - private static ConditionResolver ParseObjectExpression(object data, string expression) - { - var parts = expression.Split(' '); - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - int typeStartIndex = expression.IndexOf('<'); - int typeEndIndex = expression.IndexOf('>'); - - string memberPath; - Type type; - object? targetObj; - if (typeStartIndex + typeStartIndex == -2) - { - memberPath = operatorStr; - targetObj = GetMemberValue(data, operatorStr); - - type = targetObj.GetType(); - - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - if (typeStartIndex >= typeEndIndex) - { - throw new ArgumentException("无效的表达式格式"); - } - memberPath = expression.Substring(0, typeStartIndex).Trim(); - string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1).Trim().ToLower(); - parts = expression.Substring(typeEndIndex + 1).Trim().Split(' '); - if (parts.Length == 3) - { - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - operatorStr = parts[0].ToLower(); - valueStr = string.Join(' ', parts.Skip(1)); - } - targetObj = GetMemberValue(data, memberPath); - - Type? tempType = typeStr switch - { - "int" => typeof(int), - "double" => typeof(double), - "bool" => typeof(bool), - "string" => typeof(string), - _ => Type.GetType(typeStr) - }; - type = tempType ?? throw new ArgumentException("对象表达式无效的类型声明"); - } - - - - if (type == typeof(int)) - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - TargetObj = targetObj, - //MemberPath = memberPath, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - else if (type == typeof(bool)) - { - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = (ValueTypeConditionResolver.Operator)ParseBoolOperator(operatorStr) - }; - } - else if (type == typeof(string)) - { - return new MemberStringConditionResolver - { - MemberPath = memberPath, - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - private static ConditionResolver ParseSimpleExpression(object data, string expression) - { - if ("pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.Pass, - }; - } - else - { - if ("not pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - if ("!pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - } - - - var parts = expression.Split(' '); - - if (parts.Length < 2) - throw new ArgumentException("无效的表达式格式。"); - - //string typeStr = parts[0]; - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - Type type = data.GetType();//Type.GetType(typeStr); - if (type == typeof(int)) - { - var op = ParseValueTypeOperator(operatorStr); - if (op == ValueTypeConditionResolver.Operator.InRange || op == ValueTypeConditionResolver.Operator.OutOfRange) - { - var temp = valueStr.Split('-'); - if (temp.Length < 2) - throw new ArgumentException($"范围无效:{valueStr}。"); - int rangeStart = int.Parse(temp[0], CultureInfo.InvariantCulture); - int rangeEnd = int.Parse(temp[1], CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - RangeStart = rangeStart, - RangeEnd = rangeEnd, - ArithmeticExpression = GetArithmeticExpression(parts[0]), - }; - } - else - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(bool)) - { - bool value = bool.Parse(valueStr); - return new BoolConditionResolver - { - Op = ParseBoolOperator(operatorStr), - Value = value, - }; - } - else if (type == typeof(string)) - { - return new StringConditionResolver - { - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - - private static ValueTypeConditionResolver.Operator ParseValueTypeOperator(string operatorStr) where T : struct, IComparable - { - return operatorStr switch - { - ">" => ValueTypeConditionResolver.Operator.GreaterThan, - "<" => ValueTypeConditionResolver.Operator.LessThan, - "=" => ValueTypeConditionResolver.Operator.Equal, - "==" => ValueTypeConditionResolver.Operator.Equal, - ">=" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "≥" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "<=" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "≤" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "equals" => ValueTypeConditionResolver.Operator.Equal, - "in" => ValueTypeConditionResolver.Operator.InRange, - "!in" => ValueTypeConditionResolver.Operator.OutOfRange, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for value type.") - }; - } - - private static BoolConditionResolver.Operator ParseBoolOperator(string operatorStr) - { - return operatorStr switch - { - "is" => BoolConditionResolver.Operator.Is, - "==" => BoolConditionResolver.Operator.Is, - "equals" => BoolConditionResolver.Operator.Is, - //"isFalse" => BoolConditionNode.Operator.IsFalse, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for bool type.") - }; - } - - private static StringConditionResolver.Operator ParseStringOperator(string operatorStr) - { - return operatorStr switch - { - "c" => StringConditionResolver.Operator.Contains, - "nc" => StringConditionResolver.Operator.DoesNotContain, - "sw" => StringConditionResolver.Operator.StartsWith, - "ew" => StringConditionResolver.Operator.EndsWith, - - "contains" => StringConditionResolver.Operator.Contains, - "doesNotContain" => StringConditionResolver.Operator.DoesNotContain, - "equals" => StringConditionResolver.Operator.Equal, - "==" => StringConditionResolver.Operator.Equal, - "notEquals" => StringConditionResolver.Operator.NotEqual, - "!=" => StringConditionResolver.Operator.NotEqual, - "startsWith" => StringConditionResolver.Operator.StartsWith, - "endsWith" => StringConditionResolver.Operator.EndsWith, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for string type.") - }; - } -} diff --git a/Library.Core/ServiceContainer.cs b/Library.Core/ServiceContainer.cs deleted file mode 100644 index f8e490c..0000000 --- a/Library.Core/ServiceContainer.cs +++ /dev/null @@ -1,418 +0,0 @@ -//using Serein.Web; -//using Microsoft.Win32; -//using NetTaste; -//using System.Collections.Concurrent; -//using System.Reflection; -//using System; -//using System.Linq; -//using System.Collections.Generic; -//using SqlSugar; - -//namespace Serein -//{ - - -// public interface IServiceContainer -// { -// /// -// /// 获取或创建类型的实例(不注入依赖项) -// /// -// object GetOrCreateServiceInstance(Type serviceType, params object[] parameters); -// T CreateServiceInstance(params object[] parameters); -// IServiceContainer Reset(); // 清空 -// IServiceContainer Register(Type type, params object[] parameters); -// IServiceContainer Register(params object[] parameters); -// IServiceContainer Register(params object[] parameters) where TImplementation : TService; -// T Get(); -// object Get(Type type); - -// /// -// /// 创建目标类型的对象, 并注入依赖项 -// /// -// object? Instantiate(Type type, params object[] parameters); -// IServiceContainer Build(); -// IServiceContainer Run(Action action); -// IServiceContainer Run(Action action); -// IServiceContainer Run(Action action); -// IServiceContainer Run(Action action); -// IServiceContainer Run(Action action); -// IServiceContainer Run(Action action); -// IServiceContainer Run(Action action); -// IServiceContainer Run(Action action); -// } - -// public class ServiceContainer : IServiceContainer -// { - -// private readonly ConcurrentDictionary _dependencies; -// private readonly ConcurrentDictionary _typeMappings; -// private readonly List _waitingForInstantiation; - -// public ServiceContainer() -// { - -// _dependencies = new ConcurrentDictionary -// { -// [typeof(IServiceContainer).FullName] = this -// }; - -// _typeMappings = new ConcurrentDictionary(); -// _waitingForInstantiation = []; -// } -// public object GetOrCreateServiceInstance(Type type, params object[] parameters) -// { -// Register(type); -// object instance; - -// if (_dependencies.ContainsKey(type.FullName)) -// { -// instance = _dependencies[type.FullName]; -// } -// else -// { - -// instance = Activator.CreateInstance(type); - - -// _dependencies[type.FullName] = instance; - -// } - - -// return instance; - -// } -// public T CreateServiceInstance(params object[] parameters) -// { -// return (T)GetOrCreateServiceInstance(typeof(T), parameters); -// } - -// public IServiceContainer Reset() -// { -// foreach(var instancei in _dependencies.Values) -// { -// if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable) -// { -// disposable.Dispose(); -// } -// } -// _dependencies.Clear(); -// _waitingForInstantiation.Clear(); -// //_typeMappings.Clear(); -// return this; -// } - -// public IServiceContainer Register(Type type, params object[] parameters) -// { - -// if (!_typeMappings.ContainsKey(type.FullName)) -// { -// _typeMappings[type.FullName] = type; -// } - -// return this; -// } -// public IServiceContainer Register(params object[] parameters) -// { -// Register(typeof(T), parameters); -// return this; -// } - -// public IServiceContainer Register(params object[] parameters) -// where TImplementation : TService -// { -// _typeMappings[typeof(TService).FullName!] = typeof(TImplementation); -// return this; -// } - -// public object Get(Type type) -// { - - -// if (!_dependencies.TryGetValue(type.FullName, out object value)) -// { -// Register(type); - -// value = Instantiate(type); - -// InjectDependencies(type); -// } - - - -// return value; - -// } - - -// public T Get() -// { - - -// if(!_dependencies.TryGetValue(typeof(T).FullName, out object value)) -// { -// Register(); - -// value = Instantiate(typeof(T)); - -// } - - - - -// return (T)value; - - -// //throw new InvalidOperationException("目标类型未创建实例"); -// } -// public IServiceContainer Build() -// { -// foreach (var type in _typeMappings.Values) -// { - -// if(!_dependencies.ContainsKey(type.FullName)) -// { - -// _dependencies[type.FullName] = Activator.CreateInstance(type); - -// } - -// } - -// foreach (var instance in _dependencies.Values) -// { - -// InjectDependencies(instance); // 替换占位符 -// } - -// //var instance = Instantiate(item.Value); - -// TryInstantiateWaitingDependencies(); -// return this; -// } - -// public object? Instantiate(Type controllerType, params object[] parameters) -// { -// var instance = Activator.CreateInstance(controllerType, parameters); -// if(instance != null) -// { -// InjectDependencies(instance); -// } -// return instance; -// } - -// private void InjectDependencies(object instance) -// { -// var properties = instance.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public) -// .Where(p => p.CanWrite && p.GetCustomAttribute() != null); - -// foreach (var property in properties) -// { -// var propertyType = property.PropertyType; - -// if (_dependencies.TryGetValue(propertyType.FullName, out var dependencyInstance)) -// { -// property.SetValue(instance, dependencyInstance); -// } - -// } -// } - -// private void TryInstantiateWaitingDependencies() -// { -// foreach (var waitingType in _waitingForInstantiation.ToList()) -// { -// if (_typeMappings.TryGetValue(waitingType.FullName!, out var implementationType)) -// { -// var instance = Instantiate(implementationType); -// if (instance != null) -// { - -// _dependencies[waitingType.FullName] = instance; - -// _waitingForInstantiation.Remove(waitingType); -// } -// } -// } -// } - -// #region run() -// public IServiceContainer Run(Action action) -// { -// var service = Get(); -// if (service != null) -// { -// action(service); -// } -// return this; -// } - -// public IServiceContainer Run(Action action) -// { -// var service1 = Get(); -// var service2 = Get(); - -// action(service1, service2); -// return this; -// } - -// public IServiceContainer Run(Action action) -// { -// var service1 = Get(); -// var service2 = Get(); -// var service3 = Get(); -// action(service1, service2, service3); -// return this; -// } - -// public IServiceContainer Run(Action action) -// { -// var service1 = Get(); -// var service2 = Get(); -// var service3 = Get(); -// var service4 = Get(); -// action(service1, service2, service3, service4); -// return this; -// } - -// public IServiceContainer Run(Action action) -// { -// var service1 = Get(); -// var service2 = Get(); -// var service3 = Get(); -// var service4 = Get(); -// var service5 = Get(); -// action(service1, service2, service3, service4, service5); -// return this; -// } - -// public IServiceContainer Run(Action action) -// { -// var service1 = Get(); -// var service2 = Get(); -// var service3 = Get(); -// var service4 = Get(); -// var service5 = Get(); -// var service6 = Get(); -// action(service1, service2, service3, service4, service5, service6); -// return this; -// } - -// public IServiceContainer Run(Action action) -// { -// var service1 = Get(); -// var service2 = Get(); -// var service3 = Get(); -// var service4 = Get(); -// var service5 = Get(); -// var service6 = Get(); -// var service7 = Get(); -// action(service1, service2, service3, service4, service5, service6, service7); -// return this; -// } - -// public IServiceContainer Run(Action action) -// { -// var service1 = Get(); -// var service2 = Get(); -// var service3 = Get(); -// var service4 = Get(); -// var service5 = Get(); -// var service6 = Get(); -// var service7 = Get(); -// var service8 = Get(); -// action(service1, service2, service3, service4, service5, service6, service7, service8); -// return this; -// } - -// #endregion -// } - - -// /* public interface IServiceContainer -// { -// ServiceContainer Register(params object[] parameters); -// ServiceContainer Register(params object[] parameters) where TImplementation : TService; -// TService Resolve(); -// void Get(Action action); -// object Instantiate(Type type, params object[] parameters); - -// } -// public class ServiceContainer : IServiceContainer -// { -// private readonly Dictionary _dependencies; -// public ServiceContainer() -// { -// _dependencies = new Dictionary -// { -// [typeof(IServiceContainer)] = this -// }; -// } - -// public void Get(Action action) -// { -// var service = Resolve(); -// action(service); -// } -// public ServiceContainer Register(params object[] parameters) -// { -// var instance = Instantiate(typeof(T), parameters); -// _dependencies[typeof(T)] = instance; -// return this; -// } - -// public ServiceContainer Register(params object[] parameters) -// where TImplementation : TService -// { - -// _dependencies[typeof(TService)] = Instantiate(typeof(TImplementation), parameters); -// return this; -// } - - -// public TService Resolve() -// { -// return (TService)_dependencies[typeof(TService)]; -// } - -// public object Instantiate(Type controllerType, params object[] parameters) -// { -// var constructors = controllerType.GetConstructors(); // 获取控制器的所有构造函数 - -// // 查找具有最多参数的构造函数 -// var constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); - -// if (constructor != null) -// { -// if (parameters.Length > 0) -// { -// return Activator.CreateInstance(controllerType, parameters); -// } -// else { -// var tmpParameters = constructor.GetParameters(); -// var dependencyInstances = new List(); - -// foreach (var parameter in tmpParameters) -// { -// var parameterType = parameter.ParameterType; -// _dependencies.TryGetValue(parameterType, out var dependencyInstance); -// dependencyInstances.Add(dependencyInstance); -// if (dependencyInstance == null) -// { -// return null; -// } -// } -// // 用解析的依赖项实例化目标类型 -// return Activator.CreateInstance(controllerType, dependencyInstances.ToArray()); -// } -// } -// else -// { -// return Activator.CreateInstance(controllerType); -// } -// } -// }*/ - - - -//} diff --git a/Library.Core/Tool/DataHelper.cs b/Library.Core/Tool/DataHelper.cs deleted file mode 100644 index 14578a3..0000000 --- a/Library.Core/Tool/DataHelper.cs +++ /dev/null @@ -1,185 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.Tool -{ - public static class DataHelper - { - /// - /// 把Object转换为Json字符串 - /// - /// - /// - public static string ToJson(this object obj) - { - IsoDateTimeConverter val = new IsoDateTimeConverter(); - val.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; - IsoDateTimeConverter val2 = val; - return JsonConvert.SerializeObject(obj, (JsonConverter[])(object)new JsonConverter[1] { (JsonConverter)val2 }); - } - - - - /// - /// 把Json文本转为实体 - /// - /// - /// - /// - public static T FromJSON(this string input) - { - try - { - if (typeof(T).IsAssignableFrom(typeof(T))) - { - - } - - return JsonConvert.DeserializeObject(input); - - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - // return default(T); - - return default; - - } - } - - public static List IListToList(IList list) - { - T[] array = new T[list.Count]; - list.CopyTo(array, 0); - return new List(array); - } - - public static DataTable GetNewDataTable(DataTable dt, string condition) - { - if (!IsExistRows(dt)) - { - if (condition.Trim() == "") - { - return dt; - } - - DataTable dataTable = new DataTable(); - dataTable = dt.Clone(); - DataRow[] array = dt.Select(condition); - for (int i = 0; i < array.Length; i++) - { - dataTable.ImportRow(array[i]); - } - - return dataTable; - } - - - return null; - - } - - public static bool IsExistRows(DataTable dt) - { - if (dt != null && dt.Rows.Count > 0) - { - return false; - } - - return true; - } - - public static Hashtable DataTableToHashtable(DataTable dt) - { - Hashtable hashtable = new Hashtable(); - foreach (DataRow row in dt.Rows) - { - for (int i = 0; i < dt.Columns.Count; i++) - { - string columnName = dt.Columns[i].ColumnName; - hashtable[columnName] = row[columnName]; - } - } - - return hashtable; - } - - public static DataTable ListToDataTable(List entitys) - { - if (entitys == null || entitys.Count < 1) - { - - return null; - - } - - - Type type = entitys[0].GetType(); - - PropertyInfo[] properties = type.GetProperties(); - DataTable dataTable = new DataTable(); - for (int i = 0; i < properties.Length; i++) - { - dataTable.Columns.Add(properties[i].Name); - } - - foreach (T entity in entitys) - { - - object obj = entity; - - - if (obj.GetType() != type) - { - throw new Exception("要转换的集合元素类型不一致"); - } - - - object[] array = new object[properties.Length]; - for (int j = 0; j < properties.Length; j++) - { - - array[j] = properties[j].GetValue(obj, null); - - } - - dataTable.Rows.Add(array); - } - - return dataTable; - } - - public static string DataTableToXML(DataTable dt) - { - if (dt != null && dt.Rows.Count > 0) - { - StringWriter stringWriter = new StringWriter(); - dt.WriteXml((TextWriter)stringWriter); - return stringWriter.ToString(); - } - - return string.Empty; - } - - public static string DataSetToXML(DataSet ds) - { - if (ds != null) - { - StringWriter stringWriter = new StringWriter(); - ds.WriteXml((TextWriter)stringWriter); - return stringWriter.ToString(); - } - - return string.Empty; - } - } -} diff --git a/Library.Framework/Http/Attribute.cs b/Library.Framework/Http/Attribute.cs deleted file mode 100644 index 2971e2e..0000000 --- a/Library.Framework/Http/Attribute.cs +++ /dev/null @@ -1,167 +0,0 @@ -using Serein.Library.Framework.NodeFlow; -using System; - -namespace Serein.Library.Framework.Http -{ - - ///// - ///// 用来判断一个类是否需要注册并构建实例(单例模式场景使用) - ///// - //[AttributeUsage(AttributeTargets.Class)] - //public class DynamicFlowAttribute : Attribute - //{ - // public DynamicFlowAttribute(bool scan = true) - // { - // Scan = scan; - // } - // public bool Scan { get; set; } - //} - - ///// - ///// 标记一个方法是什么类型,加载dll后用来拖拽到画布中 - ///// - //[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - //public class MethodDetailAttribute : Attribute - //{ - - // public MethodDetailAttribute(DynamicNodeType methodDynamicType, - // string methodTips = "", - // bool scan = true, - // string lockName = "") - // { - // Scan = scan; - // MethodDynamicType = methodDynamicType; - // MethodTips = methodTips; - // LockName = lockName; - // } - // public bool Scan { get; set; } - // public string MethodTips { get; } - // public DynamicNodeType MethodDynamicType { get; } - // public string LockName { get; } - //} - - /// - /// 是否为显式参数 - /// - //[AttributeUsage(AttributeTargets.Parameter)] - //public class ExplicitAttribute : Attribute // where TEnum : Enum - //{ - //} - - - - /// - /// 表示参数为url中的数据(Get请求中不需要显式标注) - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class IsUrlDataAttribute : Attribute - { - - } - - /// - /// 表示入参参数为整个boby的数据 - /// - /// 例如:User类型含有int id、string name字段 - /// - /// ① Add(User user) - /// 请求需要传入的json为 - /// {"user":{ - /// "id":2, - /// "name":"李志忠"}} - /// - /// ② Add([Boby]User user) - /// 请求需要传入的json为 - /// {"id":2,"name":"李志忠"} - /// - /// - [AttributeUsage(AttributeTargets.Parameter)] - public sealed class IsBobyDataAttribute : Attribute - { - - } - - /// - /// 表示该控制器会被自动注册(与程序集同一命名空间,暂时不支持运行时自动加载DLL,需要手动注册) - /// - [AttributeUsage(AttributeTargets.Class)] - public sealed class AutoHostingAttribute : Attribute - { - public AutoHostingAttribute(string url = "") - { - Url = url; - } - public string Url { get; } - } - /// - /// 表示该属性为自动注入依赖项 - /// - [AttributeUsage(AttributeTargets.Property)] - public sealed class AutoInjectionAttribute : Attribute - { - } - - - /// - /// 方法的接口类型与附加URL - /// - /// - /// 假设UserController.Add()的WebAPI特性中 - /// http是HTTP.POST - /// url被显示标明“temp” - /// 那么请求的接口是POST,URL是 - /// [http://localhost:8080]/user/add/temp - /// - /// - /// - [AttributeUsage(AttributeTargets.Method)] - - public sealed class WebApiAttribute : Attribute - - { - public API Type; - public string Url; - /// - /// 方法名称不作为url的部分 - /// - public bool IsUrl; - } - [AttributeUsage(AttributeTargets.Method)] - - public sealed class ApiPostAttribute : Attribute - - { - public string Url; - /// - /// 方法名称不作为url的部分 - /// - public bool IsUrl = true; - } - [AttributeUsage(AttributeTargets.Method)] - - public sealed class ApiGetAttribute : Attribute - - { - public string Url; - /// - /// 方法名称不作为url的部分 - /// - public bool IsUrl = true; - } - /*public sealed class WebApiAttribute(API http, bool isUrl = true, string url = "") : Attribute - { - public API Http { get; } = http; - public string Url { get; } = url; - /// - /// 方法名称不作为url的部分 - /// - public bool IsUrl { get; } = isUrl; - }*/ - public enum API - { - POST, - GET, - //PUT, - //DELETE - } -} diff --git a/Library.Framework/Http/ControllerBase.cs b/Library.Framework/Http/ControllerBase.cs deleted file mode 100644 index 7eba7a1..0000000 --- a/Library.Framework/Http/ControllerBase.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace Serein.Library.Framework.Http -{ - public class ControllerBase - { - - public string Url { get; set; } - - public string BobyData { get; set; } - - public string GetLog(Exception ex) - { - return "Url : " + Url + Environment.NewLine + - "Ex : " + ex.Message + Environment.NewLine + - "Data : " + BobyData + Environment.NewLine; - } - } -} diff --git a/Library.Framework/Http/Router.cs b/Library.Framework/Http/Router.cs deleted file mode 100644 index 6e6ba99..0000000 --- a/Library.Framework/Http/Router.cs +++ /dev/null @@ -1,761 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Serein.Library.Api.Api; -using Serein.Library.Framework.IOC; -using Serein.Tool; -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Reflection; -using System.Runtime.Remoting.Messaging; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Enum = System.Enum; -using Type = System.Type; - -namespace Serein.Library.Framework.Http -{ - - - - /// - /// 路由注册与解析 - /// - public class Router - { - - private readonly ConcurrentDictionary _controllerAutoHosting; // 存储是否实例化 - private readonly ConcurrentDictionary _controllerTypes; // 存储控制器类型 - private readonly ConcurrentDictionary _controllerInstances; // 存储控制器实例对象 - private readonly ConcurrentDictionary> _routes; // 用于存储路由信息 - - private readonly ISereinIoc serviceRegistry; // 用于存储路由信息 - - //private Type PostRequest; - - public Router(ISereinIoc serviceRegistry) // 构造函数,初始化 Router 类的新实例 - { - this.serviceRegistry = serviceRegistry; - - _routes = new ConcurrentDictionary>(); // 初始化路由字典 - - _controllerAutoHosting = new ConcurrentDictionary(); // 初始化控制器实例对象字典 - _controllerTypes = new ConcurrentDictionary(); // 初始化控制器实例对象字典 - _controllerInstances = new ConcurrentDictionary(); // 初始化控制器实例对象字典 - - foreach (API method in Enum.GetValues(typeof(API))) // 遍历 HTTP 枚举类型的所有值 - { - _routes.TryAdd(method.ToString(), new ConcurrentDictionary()); // 初始化每种 HTTP 方法对应的路由字典 - } - - // 获取当前程序集 - Assembly assembly = Assembly.GetExecutingAssembly(); - - // 获取包含“Controller”名称的类型 - var controllerTypes = assembly.GetTypes() - .Where(t => t.Name.Contains("Controller")); - - Type baseAttribute = typeof(AutoHostingAttribute); - Type baseController = typeof(ControllerBase); - foreach (var controllerType in controllerTypes) - { - if (controllerType.IsSubclassOf(baseController) && controllerType.IsDefined(baseAttribute)) - { - - // 如果属于控制器,并标记了AutoHosting特性,进行自动注册 - AutoRegisterAutoController(controllerType); - } - else - { - continue; - } - } - } - - - /// - /// 自动注册 自动实例化控制器 类型 - /// - /// - public void AutoRegisterAutoController(Type controllerType) // 方法声明,用于注册并实例化控制器类型 - { - if (!controllerType.IsClass || controllerType.IsAbstract) return; // 如果不是类或者是抽象类,则直接返回 - - var autoHostingAttribute = controllerType.GetCustomAttribute(); - if (autoHostingAttribute != null) { - foreach (var method in controllerType.GetMethods()) // 遍历控制器类型的所有方法 - { - var apiGetAttribute = method.GetCustomAttribute(); - var apiPostAttribute = method.GetCustomAttribute(); - if( apiGetAttribute == null && apiPostAttribute == null ) - { - continue; - } - - - - WebApiAttribute webApiAttribute = new WebApiAttribute() - { - Type = apiGetAttribute != null ? API.GET : API.POST, - Url = apiGetAttribute != null ? apiGetAttribute.Url : apiPostAttribute.Url, - IsUrl = apiGetAttribute != null ? apiGetAttribute.IsUrl : apiPostAttribute.IsUrl, - }; - - - - if (apiPostAttribute != null) // 如果存在 WebAPIAttribute 属性 - { - var url = AddRoutesUrl(autoHostingAttribute, - webApiAttribute, - controllerType, method); - Console.WriteLine(url); - if (url == null) continue; - _controllerAutoHosting[url] = true; - _controllerTypes[url] = controllerType; - - _controllerInstances[url] = null; - - } - - - /* var routeAttribute = method.GetCustomAttribute(); // 获取方法上的 WebAPIAttribute 自定义属性 - if (routeAttribute != null) // 如果存在 WebAPIAttribute 属性 - { - var url = AddRoutesUrl(autoHostingAttribute, routeAttribute, controllerType, method); - Console.WriteLine(url); - if (url == null) continue; - _controllerAutoHosting[url] = true; - _controllerTypes[url] = controllerType; - _controllerInstances[url] = null; - }*/ - } - } - } - /// - /// 手动注册 自动实例化控制器实例 - /// - public void RegisterAutoController() // 方法声明,用于动态注册路由 - { - Type controllerType = typeof(T); // 获取控制器实例的类型 - foreach (var method in controllerType.GetMethods()) // 遍历控制器类型的所有方法 - { - var apiGetAttribute = method.GetCustomAttribute(); - var apiPostAttribute = method.GetCustomAttribute(); - if (apiGetAttribute == null && apiPostAttribute == null) - { - continue; - } - - - - WebApiAttribute webApiAttribute = new WebApiAttribute() - { - Type = apiGetAttribute != null ? API.GET : API.POST, - Url = apiGetAttribute != null ? apiGetAttribute.Url : apiPostAttribute.Url, - IsUrl = apiGetAttribute != null ? apiGetAttribute.IsUrl : apiPostAttribute.IsUrl, - }; - - - - var url = AddRoutesUrl(null, webApiAttribute, controllerType, method); - - if (url == null) continue; - _controllerAutoHosting[url] = true; - _controllerTypes[url] = controllerType; - - _controllerInstances[url] = null; - - } - } - - - /// - /// 手动注册 实例持久控制器实例 - /// - /// - public void RegisterController(TController controllerInstance) where TController : ControllerBase // 方法声明,用于动态注册路由 - { - if(controllerInstance == null) return; - Type controllerType = controllerInstance.GetType(); // 获取控制器实例的类型 - foreach (var method in controllerType.GetMethods()) // 遍历控制器类型的所有方法 - { - var apiGetAttribute = method.GetCustomAttribute(); - var apiPostAttribute = method.GetCustomAttribute(); - if (apiGetAttribute == null && apiPostAttribute == null) - { - continue; - } - - - - WebApiAttribute webApiAttribute = new WebApiAttribute() - { - Type = apiGetAttribute != null ? API.GET : API.POST, - Url = apiGetAttribute != null ? apiGetAttribute.Url : apiPostAttribute.Url, - IsUrl = apiGetAttribute != null ? apiGetAttribute.IsUrl : apiPostAttribute.IsUrl, - }; - - - - var url = AddRoutesUrl(null, webApiAttribute, controllerType, method); - - if (url == null) continue; - _controllerInstances[url] = controllerInstance; - _controllerAutoHosting[url] = false; - } - } - - /// - /// 从方法中收集路由信息 - /// - /// - public string AddRoutesUrl(AutoHostingAttribute autoHostingAttribute, WebApiAttribute webAttribute, Type controllerType, MethodInfo method) - { - string controllerName; - if (autoHostingAttribute == null || string.IsNullOrWhiteSpace(autoHostingAttribute.Url)) - { - controllerName = controllerType.Name.Replace("Controller", "").ToLower(); // 获取控制器名称并转换为小写 - } - else - { - controllerName = autoHostingAttribute.Url; - } - - var httpMethod = webAttribute.Type; // 获取 HTTP 方法 - var customUrl = webAttribute.Url; // 获取自定义 URL - - string url; - - if (webAttribute.IsUrl) - { - - if (string.IsNullOrEmpty(customUrl)) // 如果自定义 URL 为空 - { - url = $"/{controllerName}/{method.Name}".ToLower(); // 构建默认 URL - } - else - { - customUrl = CleanUrl(customUrl); - url = $"/{controllerName}/{method.Name}/{customUrl}".ToLower();// 清理自定义 URL,并构建新的 URL - } - _routes[httpMethod.ToString()].TryAdd(url, method); // 将 URL 和方法添加到对应的路由字典中 - } - else - { - if (string.IsNullOrEmpty(customUrl)) // 如果自定义 URL 为空 - { - url = $"/{controllerName}".ToLower(); // 构建默认 URL - } - else - { - customUrl = CleanUrl(customUrl); - url = $"/{controllerName}/{customUrl}".ToLower();// 清理自定义 URL,并构建新的 URL - } - _routes[httpMethod.ToString()].TryAdd(url, method); // 将 URL 和方法添加到对应的路由字典中 - } - - return url; - - } - - - /// - /// 收集路由信息 - /// - /// - public void CollectRoutes(Type controllerType) - { - string controllerName = controllerType.Name.Replace("Controller", "").ToLower(); // 获取控制器名称并转换为小写 - foreach (var method in controllerType.GetMethods()) // 遍历控制器类型的所有方法 - { - var routeAttribute = method.GetCustomAttribute(); // 获取方法上的 WebAPIAttribute 自定义属性 - if (routeAttribute != null) // 如果存在 WebAPIAttribute 属性 - { - var customUrl = routeAttribute.Url; // 获取自定义 URL - string url; - if (string.IsNullOrEmpty(customUrl)) // 如果自定义 URL 为空 - { - url = $"/api/{controllerName}/{method.Name}".ToLower(); // 构建默认 URL - } - else - { - customUrl = CleanUrl(customUrl); - url = $"/api/{controllerName}/{method.Name}/{customUrl}".ToLower();// 清理自定义 URL,并构建新的 URL - } - var httpMethod = routeAttribute.Type; // 获取 HTTP 方法 - _routes[httpMethod.ToString()].TryAdd(url, method); // 将 URL 和方法添加到对应的路由字典中 - } - } - } - - - /// - /// 解析路由,调用对应的方法 - /// - /// - /// - public async Task RouteAsync(HttpListenerContext context) - { - var request = context.Request; // 获取请求对象 - var response = context.Response; // 获取响应对象 - var url = request.Url; // 获取请求的 URL - var httpMethod = request.HttpMethod; // 获取请求的 HTTP 方法 - - var template = request.Url.AbsolutePath.ToLower(); - - - if (!_routes[httpMethod].TryGetValue(template, out MethodInfo method)) - { - return false; - } - - - - var routeValues = GetUrlData(url); // 解析 URL 获取路由参数 - - ControllerBase controllerInstance; - if (!_controllerAutoHosting[template]) - { - controllerInstance = (ControllerBase)_controllerInstances[template]; - } - else - { - - controllerInstance = (ControllerBase)serviceRegistry.Instantiate(_controllerTypes[template]);// 使用反射创建控制器实例 - - - } - - if (controllerInstance == null) - { - return false; // 未找到控制器实例 - } - - controllerInstance.Url = url.AbsolutePath; - object result; - switch (httpMethod) // 根据请求的 HTTP 方法执行不同的操作 - { - case "GET": // 如果是 GET 请求,传入方法、控制器、url参数 - result = InvokeControllerMethodWithRouteValues(method, controllerInstance, routeValues); - break; - case "POST": // POST 请求传入方法、控制器、请求体内容,url参数 - var requestBody = await ReadRequestBodyAsync(request); // 读取请求体内容 - controllerInstance.BobyData = requestBody; - var requestJObject = requestBody.FromJSON(); - - result = InvokeControllerMethod(method, controllerInstance, requestJObject, routeValues); - break; - default: - - result = null; - - break; - } - - Return(response, result); // 返回结果 - - return true; - } - - public static string GetLog(string Url, string BobyData = "") - { - return Environment.NewLine + - "Url : " + Url + Environment.NewLine + - "Data : " + BobyData + Environment.NewLine; - } - - /// - /// GET请求的控制器方法 - /// - private object InvokeControllerMethodWithRouteValues(MethodInfo method, object controllerInstance, Dictionary routeValues) - { - object[] parameters = GetMethodParameters(method, routeValues); - return InvokeMethod(method, controllerInstance, parameters); - } - - private static readonly Dictionary methodParameterCache = new Dictionary(); - /// - /// POST请求的调用控制器方法 - /// - public object InvokeControllerMethod(MethodInfo method, object controllerInstance, dynamic requestData, Dictionary routeValues) - { - object[] cachedMethodParameters; - - if (!methodParameterCache.TryGetValue(method, out ParameterInfo[] parameters)) - { - parameters = method.GetParameters(); - } - - cachedMethodParameters = new object[parameters.Length]; - - for (int i = 0; i < parameters.Length; i++) - { - string paramName = parameters[i].Name; - bool isUrlData = parameters[i].GetCustomAttribute(typeof(IsUrlDataAttribute)) != null; - bool isBobyData = parameters[i].GetCustomAttribute(typeof(IsBobyDataAttribute)) != null; - - if (isUrlData) - { - if (!string.IsNullOrEmpty(paramName) && routeValues.TryGetValue(paramName, out string value)) - { - cachedMethodParameters[i] = ConvertValue(value, parameters[i].ParameterType); - } - else - { - cachedMethodParameters[i] = null; - } - } - else if (isBobyData) - { - cachedMethodParameters[i] = ConvertValue(requestData.ToString(), parameters[i].ParameterType); - } - else - { - if (requestData.ContainsKey(paramName)) - { - if (parameters[i].ParameterType == typeof(string)) - { - cachedMethodParameters[i] = requestData[paramName].ToString(); - } - else if (parameters[i].ParameterType == typeof(bool)) - { - cachedMethodParameters[i] = requestData[paramName?.ToLower()].ToBool(); - } - else if (parameters[i].ParameterType == typeof(int)) - { - cachedMethodParameters[i] = requestData[paramName].ToInt(); - } - else if (parameters[i].ParameterType == typeof(double)) - { - cachedMethodParameters[i] = requestData[paramName].ToDouble(); - } - else - { - cachedMethodParameters[i] = ConvertValue(requestData[paramName], parameters[i].ParameterType); - } - } - else - { - cachedMethodParameters[i] = null; - } - } - } - - // 缓存方法和参数的映射 - //methodParameterCache[method] = cachedMethodParameters; - - - // 调用方法 - - return method.Invoke(controllerInstance, cachedMethodParameters); - - } - - - /// - /// 检查方法入参参数类型,返回对应的入参数组 - /// - /// - /// - /// - private object[] GetMethodParameters(MethodInfo method, Dictionary routeValues) - { - ParameterInfo[] methodParameters = method.GetParameters(); - object[] parameters = new object[methodParameters.Length]; - - for (int i = 0; i < methodParameters.Length; i++) - { - - string paramName = methodParameters[i].Name; - - - if (routeValues.TryGetValue(paramName, out string value)) - { - parameters[i] = ConvertValue(value, methodParameters[i].ParameterType); - } - else - { - - parameters[i] = null; - - } - - } - - return parameters; - } - - /*/// - /// 转为对应的类型 - /// - /// - /// - /// - private object ConvertValue(object value, Type targetType) - { - try - { - return JsonConvert.DeserializeObject(value.ToString(), targetType); - } - catch (JsonReaderException ex) - { - return value; - } - catch (JsonSerializationException ex) - { - // 如果无法转为对应的JSON对象 - int startIndex = ex.Message.IndexOf("to type '") + "to type '".Length; // 查找类型信息开始的索引 - int endIndex = ex.Message.IndexOf("'", startIndex); // 查找类型信息结束的索引 - var typeInfo = ex.Message.Substring(startIndex, endIndex - startIndex); // 提取出错类型信息,该怎么传出去? - return null; - } - catch // (Exception ex) - { - return value; - } - }*/ - /// - /// 转为对应的类型 - /// - /// - /// - /// - private object ConvertValue(string value, Type targetType) - { - if(targetType == typeof(string)) - { - return value; - } - - try - { - - return JsonConvert.DeserializeObject(value.ToString(), targetType); - - } - catch (JsonReaderException ex) - { - return value; - } - catch (JsonSerializationException ex) - { - // 如果无法转为对应的JSON对象 - int startIndex = ex.Message.IndexOf("to type '") + "to type '".Length; // 查找类型信息开始的索引 - int endIndex = ex.Message.IndexOf('\''); // 查找类型信息结束的索引 - var typeInfo = ex.Message.Substring(startIndex, endIndex); // 提取出错类型信息,该怎么传出去? - - return null; - - } - catch // (Exception ex) - { - return value; - } - } - - /// - /// 调用控制器方法传入参数 - /// - /// 方法 - /// 控制器实例 - /// 参数列表 - /// - private static object InvokeMethod(MethodInfo method, object controllerInstance, object[] methodParameters) - { - - object result = null; - - try - { - - result = method?.Invoke(controllerInstance, methodParameters); - - } - catch (ArgumentException ex) - { - string targetType = ExtractTargetTypeFromExceptionMessage(ex.Message); - - // 如果方法调用失败 - result = new - { - error = $"函数签名类型[{targetType}]不符合", - }; - } - catch (JsonSerializationException ex) - { - - // 查找类型信息开始的索引 - int startIndex = ex.Message.IndexOf("to type '") + "to type '".Length; - // 查找类型信息结束的索引 - int endIndex = ex.Message.IndexOf('\''); - // 提取类型信息 - string typeInfo = ex.Message.Substring(startIndex, endIndex); - } - catch (Exception ex) - { - Console.WriteLine(ex.ToString()); - } - - return result; // 调用方法并返回结果 - - } - - - /// - /// 方法声明,用于解析 URL 获取路由参数 - /// - /// - /// - private static Dictionary GetUrlData(Uri uri) - { - Dictionary routeValues = new Dictionary(); - - var pathParts = uri.ToString().Split('?'); // 拆分 URL,获取路径部分 - - if (pathParts.Length > 1) // 如果包含查询字符串 - { - var queryParams = HttpUtility.ParseQueryString(pathParts[1]); // 解析查询字符串 - - foreach (string key in queryParams) // 遍历查询字符串的键值对 - { - if (key == null) continue; - - routeValues[key] = queryParams[key]; // 将键值对添加到路由参数字典中 - - } - } - - return routeValues; // 返回路由参数字典 - } - - /// - /// 读取Body中的消息 - /// - /// - /// - private static async Task ReadRequestBodyAsync(HttpListenerRequest request) - { - using (Stream stream = request.InputStream) - using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) - { - return await reader.ReadToEndAsync(); - } - } - /// - /// 返回响应消息 - /// - /// - /// - private static void Return(HttpListenerResponse response, dynamic msg) - { - string resultData; - if (response != null) - { - try - { - if (msg is IEnumerable && !(msg is string)) - { - // If msg is a collection (e.g., array or list), serialize it as JArray - resultData = JArray.FromObject(msg).ToString(); - } - else - { - // Otherwise, serialize it as JObject - resultData = JObject.FromObject(msg).ToString(); - } - byte[] buffer = Encoding.UTF8.GetBytes(resultData); - response.ContentLength64 = buffer.Length; - response.OutputStream.Write(buffer, 0, buffer.Length); - } - catch - { - // If serialization fails, use the original message's string representation - resultData = msg.ToString(); - } - - - } - } - - /// - /// 解析JSON - /// - /// - /// - /// - private static dynamic ParseJson(string requestBody) - { - try - { - if (string.IsNullOrWhiteSpace(requestBody)) - { - throw new Exception("Invalid JSON format"); - } - return JObject.Parse(requestBody); - } - catch - { - throw new Exception("Invalid JSON format"); - } - } - - /// - /// 修正方法特性中的URL格式 - /// - /// - /// - private static string CleanUrl(string url) - { - - while (url.Length > 0 && url[0] == '/') // 去除开头的斜杠 - { - url = url.Substring(1,url.Length-1); - } - - while (url.Length > 0 && url[url.Length-1] == '/') // 去除末尾的斜杠 - { - url = url.Substring(0,url.Length-1); - } - - for (int i = 0; i < url.Length - 1; i++) // 去除连续的斜杠 - { - if (url[i] == '/' && url[i + 1] == '/') - { - url = url.Remove(i, 1); - i--; - } - } - - return url; // 返回清理后的 URL - } - /// - /// 从控制器调用方法的异常中获取出出错类型的信息 - /// - /// - /// - public static string ExtractTargetTypeFromExceptionMessage(string errorMessage) - { - string targetText = "为类型“"; - int startIndex = errorMessage.IndexOf(targetText); - if (startIndex != -1) - { - startIndex += targetText.Length; - int endIndex = errorMessage.IndexOf('\''); - if (endIndex != -1) - { - return errorMessage.Substring(startIndex, endIndex); - } - } - - - return null; - - } - } -} - diff --git a/Library.Framework/Http/WebAPIAttribute.cs b/Library.Framework/Http/WebAPIAttribute.cs deleted file mode 100644 index b13539f..0000000 --- a/Library.Framework/Http/WebAPIAttribute.cs +++ /dev/null @@ -1,196 +0,0 @@ -using Serein.Library.Api.Api; -using Serein.Library.Framework.IOC; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Net; -using System.Threading.Tasks; - -namespace Serein.Library.Framework.Http -{ - - /// - /// HTTP接口监听类 - /// - public class WebServer - { - private readonly HttpListener listener; // HTTP 监听器 - private Router router; // 路由器 - private readonly RequestLimiter requestLimiter; //接口防刷 - - - - public WebServer() - - { - listener = new HttpListener(); - - requestLimiter = new RequestLimiter(5, 8); - - } - - // 启动服务器 - public WebServer Start(string prefixe, ISereinIoc serviceContainer) - { - try - { - router = new Router(serviceContainer); - if (listener.IsListening) - { - return this; - } - - if (!prefixe.Substring(prefixe.Length - 1, 1).Equals(@"/")) - { - prefixe += @"/"; - } - - - listener.Prefixes.Add(prefixe); // 添加监听前缀 - listener.Start(); // 开始监听 - - Console.WriteLine($"开始监听:{prefixe}"); - Task.Run(async () => - { - while (listener.IsListening) - { - var context = await listener.GetContextAsync(); // 获取请求上下文 - _ = Task.Run(() => ProcessRequestAsync(context)); // 处理请求) - } - }); - return this; - } - catch (HttpListenerException ex) when (ex.ErrorCode == 183) - { - return this; - } - } - - - /// - /// 处理请求 - /// - /// - /// - private async Task ProcessRequestAsync(HttpListenerContext context) - { - // 添加CORS头部 - context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); - context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); - context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type"); - - // 处理OPTIONS预检请求 - if (context.Request.HttpMethod == "OPTIONS") - { - context.Response.StatusCode = (int)HttpStatusCode.OK; - context.Response.Close(); - return; - } - - var isPass = await router.RouteAsync(context); // 路由解析 - if (isPass) - { - context.Response.StatusCode = (int)HttpStatusCode.OK; - context.Response.Close(); // 关闭响应 - } - else - { - context.Response.StatusCode = (int)HttpStatusCode.NotFound; - context.Response.Close(); // 关闭响应 - } - - //var isPass = requestLimiter.AllowRequest(context.Request); - //if (isPass) - //{ - // // 如果路由没有匹配,返回 404 - // router.RouteAsync(context); // 路由解析 - //} - //else - //{ - // context.Response.StatusCode = (int)HttpStatusCode.NotFound; // 返回 404 错误 - // context.Response.Close(); // 关闭响应 - //} - - // var request = context.Request; - // 获取远程终结点信息 - //var remoteEndPoint = context.Request.RemoteEndPoint; - //// 获取用户的IP地址和端口 - //IPAddress ipAddress = remoteEndPoint.Address; - //int port = remoteEndPoint.Port; - //Console.WriteLine("外部连接:" + ipAddress.ToString() + ":" + port); - } - - // 停止服务器 - public void Stop() - { - if (listener.IsListening) - { - listener?.Stop(); // 停止监听 - listener?.Close(); // 关闭监听器 - } - } - - public void RegisterAutoController() - { - //var instance = Activator.CreateInstance(typeof(T)); - router.RegisterAutoController(); - } - - /*public void RegisterRoute(T controllerInstance) - { - router.RegisterRoute(controllerInstance); - }*/ - } - /// - /// 判断访问接口的频次是否正常 - /// - public class RequestLimiter - { - public RequestLimiter(int seconds, int maxRequests) - { - interval = TimeSpan.FromSeconds(seconds); - maxRequests = maxRequests; - } - - private readonly ConcurrentDictionary> requestHistory = new ConcurrentDictionary>(); - private readonly TimeSpan interval; - private readonly int maxRequests; - - /// - /// 判断访问接口的频次是否正常 - /// - /// - public bool AllowRequest(HttpListenerRequest request) - { - var clientIp = request.RemoteEndPoint.Address.ToString(); - var clientPort = request.RemoteEndPoint.Port; - var clientKey = clientIp + ":" + clientPort; - - var now = DateTime.Now; - - // 尝试从字典中获取请求队列,不存在则创建新的队列 - var requests = requestHistory.GetOrAdd(clientKey, new Queue()); - - lock (requests) - { - // 移除超出时间间隔的请求记录 - while (requests.Count > 0 && now - requests.Peek() > interval) - { - requests.Dequeue(); - } - - // 如果请求数超过限制,拒绝请求 - if (requests.Count >= maxRequests) - { - return false; - } - - // 添加当前请求时间,并允许请求 - requests.Enqueue(now); - } - - return true; - } - } - -} diff --git a/Library.Framework/IOC/SereinIoc.cs b/Library.Framework/IOC/SereinIoc.cs deleted file mode 100644 index 2842b93..0000000 --- a/Library.Framework/IOC/SereinIoc.cs +++ /dev/null @@ -1,378 +0,0 @@ -using Serein.Library.Api; -using Serein.Library.Attributes; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace Serein.Library.Framework.IOC -{ - - public class SereinIoc : ISereinIoc - { - - private readonly ConcurrentDictionary _dependencies; - private readonly ConcurrentDictionary _typeMappings; - private readonly List _waitingForInstantiation; - - public SereinIoc() - { - - _dependencies = new ConcurrentDictionary - { - [typeof(ISereinIoc).FullName] = this - }; - - _typeMappings = new ConcurrentDictionary(); - _waitingForInstantiation = new List(); - } - public object GetOrCreateServiceInstance(Type type, params object[] parameters) - { - Register(type); - object instance; - - if (_dependencies.ContainsKey(type.FullName)) - { - instance = _dependencies[type.FullName]; - } - else - { - - instance = Activator.CreateInstance(type); - - - _dependencies[type.FullName] = instance; - - } - - - return instance; - - } - public T CreateServiceInstance(params object[] parameters) - { - return (T)GetOrCreateServiceInstance(typeof(T), parameters); - } - - public ISereinIoc Reset() - { - foreach(var instancei in _dependencies.Values) - { - if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable) - { - disposable.Dispose(); - } - } - _dependencies.Clear(); - _waitingForInstantiation.Clear(); - //_typeMappings.Clear(); - return this; - } - - public ISereinIoc Register(Type type, params object[] parameters) - { - - if (!_typeMappings.ContainsKey(type.FullName)) - { - _typeMappings[type.FullName] = type; - } - - return this; - } - public ISereinIoc Register(params object[] parameters) - { - Register(typeof(T), parameters); - return this; - } - - public ISereinIoc Register(params object[] parameters) - where TImplementation : TService - { - _typeMappings[typeof(TService).FullName] = typeof(TImplementation); - return this; - } - - public object GetOrInstantiate(Type type) - { - - - if (!_dependencies.TryGetValue(type.FullName, out object value)) - { - Register(type); - - value = Instantiate(type); - - InjectDependencies(type); - } - - - - return value; - - } - - - public T GetOrInstantiate() - { - if(!_dependencies.TryGetValue(typeof(T).FullName, out object value)) - { - Register(); - - value = Instantiate(typeof(T)); - } - - return (T)value; - //throw new InvalidOperationException("目标类型未创建实例"); - } - public ISereinIoc Build() - { - foreach (var type in _typeMappings.Values) - { - - if(!_dependencies.ContainsKey(type.FullName)) - { - - _dependencies[type.FullName] = Activator.CreateInstance(type); - - } - - } - - foreach (var instance in _dependencies.Values) - { - - InjectDependencies(instance); // 替换占位符 - } - - //var instance = Instantiate(item.Value); - - TryInstantiateWaitingDependencies(); - return this; - } - - public object Instantiate(Type controllerType, params object[] parameters) - { - var instance = Activator.CreateInstance(controllerType, parameters); - if(instance != null) - { - InjectDependencies(instance); - } - return instance; - } - - private void InjectDependencies(object instance) - { - var properties = instance.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).ToArray() - .Where(p => p.CanWrite && p.GetCustomAttribute() != null); - - foreach (var property in properties) - { - var propertyType = property.PropertyType; - - if (_dependencies.TryGetValue(propertyType.FullName, out var dependencyInstance)) - { - property.SetValue(instance, dependencyInstance); - } - - } - } - - private void TryInstantiateWaitingDependencies() - { - foreach (var waitingType in _waitingForInstantiation.ToList()) - { - if (_typeMappings.TryGetValue(waitingType.FullName, out var implementationType)) - { - var instance = Instantiate(implementationType); - if (instance != null) - { - - _dependencies[waitingType.FullName] = instance; - - _waitingForInstantiation.Remove(waitingType); - } - } - } - } - - #region run() - public ISereinIoc Run(Action action) - { - var service = GetOrInstantiate(); - if (service != null) - { - action(service); - } - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - - action(service1, service2); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - action(service1, service2, service3); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - action(service1, service2, service3, service4); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - var service6 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5, service6); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - var service6 = GetOrInstantiate(); - var service7 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5, service6, service7); - return this; - } - - public ISereinIoc Run(Action action) - { - var service1 = GetOrInstantiate(); - var service2 = GetOrInstantiate(); - var service3 = GetOrInstantiate(); - var service4 = GetOrInstantiate(); - var service5 = GetOrInstantiate(); - var service6 = GetOrInstantiate(); - var service7 = GetOrInstantiate(); - var service8 = GetOrInstantiate(); - action(service1, service2, service3, service4, service5, service6, service7, service8); - return this; - } - - #endregion - } - - - /* public interface IServiceContainer - { - ServiceContainer Register(params object[] parameters); - ServiceContainer Register(params object[] parameters) where TImplementation : TService; - TService Resolve(); - void Get(Action action); - object Instantiate(Type type, params object[] parameters); - - } - public class ServiceContainer : IServiceContainer - { - private readonly Dictionary _dependencies; - public ServiceContainer() - { - _dependencies = new Dictionary - { - [typeof(IServiceContainer)] = this - }; - } - - public void Get(Action action) - { - var service = Resolve(); - action(service); - } - public ServiceContainer Register(params object[] parameters) - { - var instance = Instantiate(typeof(T), parameters); - _dependencies[typeof(T)] = instance; - return this; - } - - public ServiceContainer Register(params object[] parameters) - where TImplementation : TService - { - - _dependencies[typeof(TService)] = Instantiate(typeof(TImplementation), parameters); - return this; - } - - - public TService Resolve() - { - return (TService)_dependencies[typeof(TService)]; - } - - public object Instantiate(Type controllerType, params object[] parameters) - { - var constructors = controllerType.GetConstructors(); // 获取控制器的所有构造函数 - - // 查找具有最多参数的构造函数 - var constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); - - if (constructor != null) - { - if (parameters.Length > 0) - { - return Activator.CreateInstance(controllerType, parameters); - } - else { - var tmpParameters = constructor.GetParameters(); - var dependencyInstances = new List(); - - foreach (var parameter in tmpParameters) - { - var parameterType = parameter.ParameterType; - _dependencies.TryGetValue(parameterType, out var dependencyInstance); - dependencyInstances.Add(dependencyInstance); - if (dependencyInstance == null) - { - return null; - } - } - // 用解析的依赖项实例化目标类型 - return Activator.CreateInstance(controllerType, dependencyInstances.ToArray()); - } - } - else - { - return Activator.CreateInstance(controllerType); - } - } - }*/ - - - -} diff --git a/Library.Framework/NodeFlow/Api.cs b/Library.Framework/NodeFlow/Api.cs deleted file mode 100644 index e0b48ac..0000000 --- a/Library.Framework/NodeFlow/Api.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.Library.Framework.NodeFlow -{ - public interface IDynamicFlowNode - { - } - -} diff --git a/Library.Framework/NodeFlow/DynamicNodeFrameworkType.cs b/Library.Framework/NodeFlow/DynamicNodeFrameworkType.cs deleted file mode 100644 index c1a9b5f..0000000 --- a/Library.Framework/NodeFlow/DynamicNodeFrameworkType.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.LibraryFramework.NodeFlow -{ - public enum DynamicNodeFrameworkType - { - /// - /// 初始化 - /// - Init, - /// - /// 开始载入 - /// - Loading, - /// - /// 结束 - /// - Exit, - - /// - /// 触发器 - /// - Flipflop, - /// - /// 条件节点 - /// - Condition, - /// - /// 动作节点 - /// - Action, - } - -} diff --git a/Library.Framework/NodeFlow/FlowStateType.cs b/Library.Framework/NodeFlow/FlowStateType.cs deleted file mode 100644 index 7760a19..0000000 --- a/Library.Framework/NodeFlow/FlowStateType.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.Library.Framework.NodeFlow -{ - - //public enum FlowStateType - //{ - // /// - // /// 成功(方法成功执行) - // /// - // Succeed, - // /// - // /// 失败(方法没有成功执行,不过执行时没有发生非预期的错误) - // /// - // Fail, - // /// - // /// 异常(节点没有成功执行,执行时发生非预期的错误) - // /// - // Error, - //} -} diff --git a/Library.Framework/NodeFlow/Tool/Attribute.cs b/Library.Framework/NodeFlow/Tool/Attribute.cs deleted file mode 100644 index 1b82d58..0000000 --- a/Library.Framework/NodeFlow/Tool/Attribute.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Serein.Library.Api.Enums; -using System; - -namespace Serein.Library.Framework.NodeFlow.Tool -{ - - -} diff --git a/Library.Framework/NodeFlow/Tool/DynamicTool.cs b/Library.Framework/NodeFlow/Tool/DynamicTool.cs deleted file mode 100644 index b1862fa..0000000 --- a/Library.Framework/NodeFlow/Tool/DynamicTool.cs +++ /dev/null @@ -1,194 +0,0 @@ -namespace Serein.Library.Framework.NodeFlow.Tool -{ - - #region 锁、tsk工具 (已注释) - /*public class LockManager - { - private readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); - - public void CreateLock(string name) - { - _locks.TryAdd(name, new LockQueue()); - } - - public async Task AcquireLockAsync(string name, CancellationToken cancellationToken = default) - { - if (!_locks.ContainsKey(name)) - { - throw new ArgumentException($"Lock with name '{name}' does not exist."); - } - - var lockQueue = _locks[name]; - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - lock (lockQueue.Queue) - { - lockQueue.Queue.Enqueue(tcs); - if (lockQueue.Queue.Count == 1) - { - tcs.SetResult(true); - } - } - - await tcs.Task.ConfigureAwait(false); - - // 处理取消操作 - if (cancellationToken.CanBeCanceled) - { - cancellationToken.Register(() => - { - lock (lockQueue.Queue) - { - if (lockQueue.Queue.Contains(tcs)) - { - tcs.TrySetCanceled(); - } - } - }); - } - } - - public void ReleaseLock(string name) - { - if (!_locks.ContainsKey(name)) - { - throw new ArgumentException($"Lock with name '{name}' does not exist."); - } - - var lockQueue = _locks[name]; - - lock (lockQueue.Queue) - { - if (lockQueue.Queue.Count > 0) - { - lockQueue.Queue.Dequeue(); - - if (lockQueue.Queue.Count > 0) - { - var next = lockQueue.Queue.Peek(); - next.SetResult(true); - } - } - } - } - - private class LockQueue - { - public Queue> Queue { get; } = new Queue>(); - } - } - - - public interface ITaskResult - { - object Result { get; } - } - - public class TaskResult : ITaskResult - { - public TaskResult(T result) - { - Result = result; - } - - public T Result { get; } - - object ITaskResult.Result => Result; - } - - public class DynamicTasks - { - private static readonly ConcurrentDictionary> TaskGuidPairs = new(); - public static Task GetTask(string Guid) - { - TaskGuidPairs.TryGetValue(Guid, out Task task); - return task; - } - - public static bool AddTask(string Guid, T result) - { - var task = Task.FromResult(new TaskResult(result)); - - return TaskGuidPairs.TryAdd(Guid, task); - } - } - public class TaskNodeManager - { - private readonly ConcurrentDictionary _taskQueues = new ConcurrentDictionary(); - - public void CreateTaskNode(string name) - { - _taskQueues.TryAdd(name, new TaskQueue()); - } - - public async Task WaitForTaskNodeAsync(string name, CancellationToken cancellationToken = default) - { - if (!_taskQueues.ContainsKey(name)) - { - throw new ArgumentException($"Task node with name '{name}' does not exist."); - } - - var taskQueue = _taskQueues[name]; - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - lock (taskQueue.Queue) - { - taskQueue.Queue.Enqueue(tcs); - if (taskQueue.Queue.Count == 1) - { - tcs.SetResult(true); - } - } - - await tcs.Task.ConfigureAwait(false); - - // 处理取消操作 - if (cancellationToken.CanBeCanceled) - { - cancellationToken.Register(() => - { - lock (taskQueue.Queue) - { - if (taskQueue.Queue.Contains(tcs)) - { - tcs.TrySetCanceled(); - } - } - }); - } - } - - public void CompleteTaskNode(string name) - { - if (!_taskQueues.ContainsKey(name)) - { - throw new ArgumentException($"Task node with name '{name}' does not exist."); - } - - var taskQueue = _taskQueues[name]; - - lock (taskQueue.Queue) - { - if (taskQueue.Queue.Count > 0) - { - taskQueue.Queue.Dequeue(); - - if (taskQueue.Queue.Count > 0) - { - var next = taskQueue.Queue.Peek(); - next.SetResult(true); - } - } - } - } - - private class TaskQueue - { - public Queue> Queue { get; } = new Queue>(); - } - }*/ - #endregion - - - -} diff --git a/Library.Framework/NodeFlow/Tool/TcsSignal.cs b/Library.Framework/NodeFlow/Tool/TcsSignal.cs deleted file mode 100644 index 6989b6e..0000000 --- a/Library.Framework/NodeFlow/Tool/TcsSignal.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Serein.Library.Enums; -using System; -using System.Collections.Concurrent; -using System.Threading.Tasks; - -namespace Serein.Library.Framework.NodeFlow.Tool -{ - public class TcsSignalException : Exception - { - public FlowStateType FsState { get; set; } - public TcsSignalException(string message) : base(message) - { - FsState = FlowStateType.Error; - } - } - - public class TcsSignal where TSignal : struct, Enum - { - //public ConcurrentDictionary>> TcsEvent { get; } = new(); - public ConcurrentDictionary> TcsEvent { get; } = new ConcurrentDictionary>(); - - public ConcurrentDictionary TcsLock { get; } = new ConcurrentDictionary(); - - /// - /// 触发信号 - /// - /// - /// 信号 - /// 传递的参数 - /// 是否成功触发 - public bool TriggerSignal(TSignal signal, T value) - { - var tcsLock = TcsLock.GetOrAdd(signal, new object()); - lock (tcsLock) - { - if (TcsEvent.TryRemove(signal, out var waitTcs)) - { - waitTcs.SetResult(value); - return true; - } - return false; - } - } - - public TaskCompletionSource CreateTcs(TSignal signal) - { - var tcsLock = TcsLock.GetOrAdd(signal, new object()); - lock (tcsLock) - { - var tcs = TcsEvent.GetOrAdd(signal, new TaskCompletionSource()); - return tcs; - } - - } - - public void CancelTask() - { - foreach (var tcs in TcsEvent.Values) - { - tcs.SetException(new TcsSignalException("任务取消")); - } - TcsEvent.Clear(); - } - } -} diff --git a/Library.Framework/Tool/DataHelper.cs b/Library.Framework/Tool/DataHelper.cs deleted file mode 100644 index a2140e7..0000000 --- a/Library.Framework/Tool/DataHelper.cs +++ /dev/null @@ -1,186 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.Tool -{ - public static class DataHelper - { - /// - /// 把Object转换为Json字符串 - /// - /// - /// - public static string ToJson(this object obj) - { - IsoDateTimeConverter val = new IsoDateTimeConverter(); - val.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; - IsoDateTimeConverter val2 = val; - return JsonConvert.SerializeObject(obj, (JsonConverter[])(object)new JsonConverter[1] { (JsonConverter)val2 }); - } - - - - /// - /// 把Json文本转为实体 - /// - /// - /// - /// - public static T FromJSON(this string input) - { - try - { - if (typeof(T).IsAssignableFrom(typeof(T))) - { - - } - - return JsonConvert.DeserializeObject(input); - - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - // return default(T); - - return default; - - } - } - - public static List IListToList(IList list) - { - T[] array = new T[list.Count]; - list.CopyTo(array, 0); - return new List(array); - } - - public static DataTable GetNewDataTable(DataTable dt, string condition) - { - if (!IsExistRows(dt)) - { - if (condition.Trim() == "") - { - return dt; - } - - DataTable dataTable = new DataTable(); - dataTable = dt.Clone(); - DataRow[] array = dt.Select(condition); - for (int i = 0; i < array.Length; i++) - { - dataTable.ImportRow(array[i]); - } - - return dataTable; - } - - - return null; - - } - - public static bool IsExistRows(DataTable dt) - { - if (dt != null && dt.Rows.Count > 0) - { - return false; - } - - return true; - } - - public static Hashtable DataTableToHashtable(DataTable dt) - { - Hashtable hashtable = new Hashtable(); - foreach (DataRow row in dt.Rows) - { - for (int i = 0; i < dt.Columns.Count; i++) - { - string columnName = dt.Columns[i].ColumnName; - hashtable[columnName] = row[columnName]; - } - } - - return hashtable; - } - - public static DataTable ListToDataTable(List entitys) - { - if (entitys == null || entitys.Count < 1) - { - - return null; - - } - - - Type type = entitys[0].GetType(); - - PropertyInfo[] properties = type.GetProperties(); - DataTable dataTable = new DataTable(); - for (int i = 0; i < properties.Length; i++) - { - dataTable.Columns.Add(properties[i].Name); - } - - foreach (T entity in entitys) - { - - object obj = entity; - - - if (obj.GetType() != type) - { - throw new Exception("要转换的集合元素类型不一致"); - } - - - object[] array = new object[properties.Length]; - for (int j = 0; j < properties.Length; j++) - { - - array[j] = properties[j].GetValue(obj, null); - - } - - dataTable.Rows.Add(array); - } - - return dataTable; - } - - public static string DataTableToXML(DataTable dt) - { - if (dt != null && dt.Rows.Count > 0) - { - StringWriter stringWriter = new StringWriter(); - dt.WriteXml((TextWriter)stringWriter); - return stringWriter.ToString(); - } - - return string.Empty; - } - - public static string DataSetToXML(DataSet ds) - { - if (ds != null) - { - StringWriter stringWriter = new StringWriter(); - ds.WriteXml((TextWriter)stringWriter); - return stringWriter.ToString(); - } - - return string.Empty; - } - } -} diff --git a/Library/Api/ISereinIoc.cs b/Library/Api/ISereinIoc.cs index 7e7b914..d4aee92 100644 --- a/Library/Api/ISereinIoc.cs +++ b/Library/Api/ISereinIoc.cs @@ -10,19 +10,12 @@ namespace Serein.Library.Api /// 获取或创建类型的实例(不注入依赖项) /// object GetOrCreateServiceInstance(Type serviceType, params object[] parameters); - T CreateServiceInstance(params object[] parameters); + T GetOrCreateServiceInstance(params object[] parameters); /// /// 清空 /// /// ISereinIoc Reset(); - - /// - /// 以已存在的实例对象注册 - /// - /// - /// - ISereinIoc RegisterInstantiate(object instantiate); /// /// 注册实例 /// diff --git a/Library/Base/NodeBase.cs b/Library/Base/NodeBase.cs deleted file mode 100644 index fe8ac44..0000000 --- a/Library/Base/NodeBase.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Serein.Library.Entity; -using Serein.Library.Enums; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Serein.Library.Base -{ - public abstract class NodeBase - { - /// - /// 节点类型 - /// - public abstract NodeControlType ControlType { get; set; } - - /// - /// 方法描述,对应DLL的方法 - /// - public abstract MethodDetails MethodDetails { get; set; } - - /// - /// 节点guid - /// - public abstract string Guid { get; set; } - - /// - /// 显示名称 - /// - public abstract string DisplayName { get; set; } - - /// - /// 是否为起点控件 - /// - public abstract bool IsStart { get; set; } - - /// - /// 运行时的上一节点 - /// - public abstract NodeBase PreviousNode { get; set; } - - /// - /// 上一节点集合 - /// - public abstract List PreviousNodes { get; set; } - - /// - /// 下一节点集合(真分支) - /// - public abstract List SucceedBranch { get; set; } - - /// - /// 下一节点集合(假分支) - /// - public abstract List FailBranch { get; set; } - - /// - /// 异常分支 - /// - public abstract List ErrorBranch { get; set; } - - /// - /// 上游分支 - /// - public abstract List UpstreamBranch { get; set; } - - /// - /// 当前执行状态(进入真分支还是假分支,异常分支在异常中确定) - /// - public abstract FlowStateType FlowState { get; set; } - - /// - /// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值) - /// - public abstract Exception RuningException { get; set; } - - /// - /// 当前传递数据(执行了节点对应的方法,才会存在值) - /// - public abstract object FlowData { get; set; } - - } -} diff --git a/Library/Base/NodeModelBaseData.cs b/Library/Base/NodeModelBaseData.cs deleted file mode 100644 index 7c8e260..0000000 --- a/Library/Base/NodeModelBaseData.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Serein.Library.Api; -using Serein.Library.Entity; -using Serein.Library.Enums; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Serein.Library.Base -{ - /// - /// 节点基类(数据):条件控件,动作控件,条件区域,动作区域 - /// - public abstract partial class NodeModelBase : IDynamicFlowNode - { - public NodeControlType ControlType { get; set; } - - /// - /// 方法描述,对应DLL的方法 - /// - public MethodDetails MethodDetails { get; set; } - - /// - /// 节点guid - /// - public string Guid { get; set; } - - /// - /// 显示名称 - /// - public string DisplayName { get; set; } - - /// - /// 是否为起点控件 - /// - public bool IsStart { get; set; } - - /// - /// 运行时的上一节点 - /// - public NodeModelBase PreviousNode { get; set; } - - /// - /// 上一节点集合 - /// - public List PreviousNodes { get; set; } = new List(); - - /// - /// 下一节点集合(真分支) - /// - public List SucceedBranch { get; set; } = new List(); - - /// - /// 下一节点集合(假分支) - /// - public List FailBranch { get; set; } = new List(); - - /// - /// 异常分支 - /// - public List ErrorBranch { get; set; } = new List(); - - /// - /// 上游分支 - /// - public List UpstreamBranch { get; set; } = new List(); - - /// - /// 当前执行状态(进入真分支还是假分支,异常分支在异常中确定) - /// - public FlowStateType FlowState { get; set; } = FlowStateType.None; - - /// - /// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值) - /// - public Exception RuningException { get; set; } = null; - - /// - /// 当前传递数据(执行了节点对应的方法,才会存在值) - /// - public object FlowData { get; set; } = null; - - public abstract Parameterdata[] GetParameterdatas(); - public virtual NodeInfo ToInfo() - { - if (MethodDetails == null) return null; - - var trueNodes = SucceedBranch.Select(item => item.Guid); // 真分支 - var falseNodes = FailBranch.Select(item => item.Guid);// 假分支 - var upstreamNodes = UpstreamBranch.Select(item => item.Guid);// 上游分支 - var errorNodes = ErrorBranch.Select(item => item.Guid);// 异常分支 - - // 生成参数列表 - Parameterdata[] parameterData = GetParameterdatas(); - - return new NodeInfo - { - Guid = Guid, - MethodName = MethodDetails?.MethodName, - Label = DisplayName ?? "", - Type = this.GetType().ToString(), - TrueNodes = trueNodes.ToArray(), - FalseNodes = falseNodes.ToArray(), - UpstreamNodes = upstreamNodes.ToArray(), - ParameterData = parameterData.ToArray(), - ErrorNodes = errorNodes.ToArray(), - }; - } - - } -} diff --git a/Library/Base/NodeModelBaseFunc.cs b/Library/Base/NodeModelBaseFunc.cs deleted file mode 100644 index 1c53181..0000000 --- a/Library/Base/NodeModelBaseFunc.cs +++ /dev/null @@ -1,480 +0,0 @@ -using Newtonsoft.Json; -using Serein.Library.Api; -using Serein.Library.Entity; -using Serein.Library.Enums; -using Serein.Library.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace Serein.Library.Base -{ - /// - /// 节点基类(数据):条件控件,动作控件,条件区域,动作区域 - /// - public abstract partial class NodeModelBase : IDynamicFlowNode - { - /// - /// 执行节点对应的方法 - /// - /// 流程上下文 - /// 节点传回数据对象 - public virtual object Execute(IDynamicContext context) - { - MethodDetails md = MethodDetails; - object result = null; - var del = md.MethodDelegate; - try - { - if (md.ExplicitDatas.Length == 0) - { - if (md.ReturnType == typeof(void)) - { - ((Action)del).Invoke(md.ActingInstance); - } - else - { - result = ((Func)del).Invoke(md.ActingInstance); - } - } - else - { - object[] parameters = GetParameters(context, MethodDetails); - if (md.ReturnType == typeof(void)) - { - ((Action)del).Invoke(md.ActingInstance, parameters); - } - else - { - result = ((Func)del).Invoke(md.ActingInstance, parameters); - } - } - - return result; - } - catch (Exception ex) - { - FlowState = FlowStateType.Error; - RuningException = ex; - } - - return result; - } - - /// - /// 执行等待触发器的方法 - /// - /// - /// 节点传回数据对象 - /// - public virtual async Task ExecuteAsync(IDynamicContext context) - { - MethodDetails md = MethodDetails; - object result = null; - - IFlipflopContext flipflopContext = null; - try - { - // 调用委托并获取结果 - if (md.ExplicitDatas.Length == 0) - { - flipflopContext = await ((Func>)md.MethodDelegate).Invoke(MethodDetails.ActingInstance); - } - else - { - object[] parameters = GetParameters(context, MethodDetails); - flipflopContext = await ((Func>)md.MethodDelegate).Invoke(MethodDetails.ActingInstance, parameters); - } - - if (flipflopContext != null) - { - FlowState = flipflopContext.State; - if (flipflopContext.State == FlowStateType.Succeed) - { - result = flipflopContext.Data; - } - else - { - result = null; - } - } - } - catch (Exception ex) - { - FlowState = FlowStateType.Error; - RuningException = ex; - } - - return result; - } - - /// - /// 开始执行 - /// - /// - /// - public async Task StartExecution(IDynamicContext context) - { - var cts = context.SereinIoc.GetOrInstantiate(); - - Stack stack = new Stack(); - stack.Push(this); - - while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环 - { - // 从栈中弹出一个节点作为当前节点进行处理 - var currentNode = stack.Pop(); - - // 设置方法执行的对象 - if (currentNode.MethodDetails != null) - { - if(currentNode.MethodDetails.ActingInstance == null) - { - currentNode.MethodDetails.ActingInstance = context.SereinIoc.GetOrInstantiate(MethodDetails.ActingInstanceType); - - } - } - - // 获取上游分支,首先执行一次 - var upstreamNodes = currentNode.UpstreamBranch; - for (int i = upstreamNodes.Count - 1; i >= 0; i--) - { - upstreamNodes[i].PreviousNode = currentNode; - await upstreamNodes[i].StartExecution(context); - } - - if (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == NodeType.Flipflop) - { - // 触发器节点 - currentNode.FlowData = await currentNode.ExecuteAsync(context); - } - else - { - // 动作节点 - currentNode.FlowData = currentNode.Execute(context); - } - - List nextNodes = null ; - switch (currentNode.FlowState) - { - case FlowStateType.Succeed: - nextNodes = currentNode.SucceedBranch; - break; - case FlowStateType.Fail : - nextNodes = currentNode.FailBranch; - break; - case FlowStateType.Error : - nextNodes = currentNode.ErrorBranch; - break; - } - if(nextNodes != null) - { - for (int i = nextNodes.Count - 1; i >= 0; i--) - { - nextNodes[i].PreviousNode = currentNode; - stack.Push(nextNodes[i]); - } - } - /*var nextNodes = currentNode.FlowState switch - { - FlowStateType.Succeed => currentNode.SucceedBranch, - FlowStateType.Fail => currentNode.FailBranch, - FlowStateType.Error => currentNode.ErrorBranch, - _ => throw new Exception("非预期的枚举值") - };*/ - - // 将下一个节点集合中的所有节点逆序推入栈中 - - } - } - - /// - /// 获取对应的参数数组 - /// - public object[] GetParameters(IDynamicContext context, MethodDetails md) - { - // 用正确的大小初始化参数数组 - var types = md.ExplicitDatas.Select(it => it.DataType).ToArray(); - if (types.Length == 0) - { - return new object[] { md.ActingInstance }; - } - - object[] parameters = new object[types.Length]; - - for (int i = 0; i < types.Length; i++) - { - - var mdEd = md.ExplicitDatas[i]; - Type type = mdEd.DataType; - - var f1 = PreviousNode?.FlowData?.GetType(); - var f2 = mdEd.DataType; - if (type == typeof(IDynamicContext)) - { - parameters[i] = context; - } - else if (type == typeof(MethodDetails)) - { - parameters[i] = md; - } - else if (type == typeof(NodeModelBase)) - { - parameters[i] = this; - } - else if (mdEd.IsExplicitData) // 显式参数 - { - // 判断是否使用表达式解析 - if (mdEd.DataValue[0] == '@') - { - var expResult = SerinExpressionEvaluator.Evaluate(mdEd.DataValue, PreviousNode?.FlowData, out bool isChange); - - - if (mdEd.DataType.IsEnum) - { - var enumValue = Enum.Parse(mdEd.DataType, mdEd.DataValue); - parameters[i] = enumValue; - } - else if (mdEd.ExplicitType == typeof(string)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(string)); - } - else if (mdEd.ExplicitType == typeof(bool)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(bool)); - } - else if (mdEd.ExplicitType == typeof(int)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(int)); - } - else if (mdEd.ExplicitType == typeof(double)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(double)); - } - else - { - parameters[i] = expResult; - //parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType); - } - } - else - { - if (mdEd.DataType.IsEnum) - { - var enumValue = Enum.Parse(mdEd.DataType, mdEd.DataValue); - parameters[i] = enumValue; - } - else if (mdEd.ExplicitType == typeof(string)) - { - parameters[i] = mdEd.DataValue; - } - else if (mdEd.ExplicitType == typeof(bool)) - { - parameters[i] = bool.Parse(mdEd.DataValue); - } - else if (mdEd.ExplicitType == typeof(int)) - { - parameters[i] = int.Parse(mdEd.DataValue); - } - else if (mdEd.ExplicitType == typeof(double)) - { - parameters[i] = double.Parse(mdEd.DataValue); - } - else - { - parameters[i] = ""; - - //parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType); - } - } - - - } - else if (f1 != null && f2 != null) - { - if (f2.IsAssignableFrom(f1) || f2.FullName.Equals(f1.FullName)) - { - parameters[i] = PreviousNode?.FlowData; - - } - } - else - { - - - var tmpParameter = PreviousNode?.FlowData?.ToString(); - if (mdEd.DataType.IsEnum) - { - - var enumValue = Enum.Parse(mdEd.DataType, tmpParameter); - - parameters[i] = enumValue; - } - else if (mdEd.DataType == typeof(string)) - { - - parameters[i] = tmpParameter; - - } - else if (mdEd.DataType == typeof(bool)) - { - - parameters[i] = bool.Parse(tmpParameter); - - } - else if (mdEd.DataType == typeof(int)) - { - - parameters[i] = int.Parse(tmpParameter); - - } - else if (mdEd.DataType == typeof(double)) - { - - parameters[i] = double.Parse(tmpParameter); - - } - else - { - if (tmpParameter != null && mdEd.DataType != null) - { - - parameters[i] = ConvertValue(tmpParameter, mdEd.DataType); - - } - } - } - - } - return parameters; - } - - /// - /// json文本反序列化为对象 - /// - /// - /// - /// - private dynamic ConvertValue(string value, Type targetType) - { - try - { - if (!string.IsNullOrEmpty(value)) - { - return JsonConvert.DeserializeObject(value, targetType); - } - else - { - return null; - } - } - catch (JsonReaderException ex) - { - Console.WriteLine(ex); - return value; - } - catch (JsonSerializationException ex) - { - // 如果无法转为对应的JSON对象 - int startIndex = ex.Message.IndexOf("to type '") + "to type '".Length; // 查找类型信息开始的索引 - int endIndex = ex.Message.IndexOf('\''); // 查找类型信息结束的索引 - var typeInfo = ex.Message.Substring(startIndex,endIndex); // 提取出错类型信息,该怎么传出去? - Console.WriteLine("无法转为对应的JSON对象:" + typeInfo); - return null; - } - catch // (Exception ex) - { - return value; - } - } - - - - - - #region 完整的ExecuteAsync调用方法(不要删除) - //public virtual async Task ExecuteAsync(DynamicContext context) - //{ - // MethodDetails md = MethodDetails; - // object? result = null; - // if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - // { - // if (md.ExplicitDatas.Length == 0) - // { - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance); - // } - // else if (md.ReturnType == typeof(Task)) - // { - // // 调用委托并获取结果 - // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance); - - // if (flipflopContext != null) - // { - // if (flipflopContext.State == FfState.Cancel) - // { - // throw new Exception("this async task is cancel."); - // } - // else - // { - // if (flipflopContext.State == FfState.Succeed) - // { - // CurrentState = true; - // result = flipflopContext.Data; - // } - // else - // { - // CurrentState = false; - // } - // } - // } - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance); - // } - // } - // else - // { - // object?[]? parameters = GetParameters(context, MethodDetails); - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance, parameters); - // } - // else if (md.ReturnType == typeof(Task)) - // { - // // 调用委托并获取结果 - // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance, parameters); - - // if (flipflopContext != null) - // { - // if (flipflopContext.State == FfState.Cancel) - // { - // throw new Exception("取消此异步"); - // } - // else - // { - // CurrentState = flipflopContext.State == FfState.Succeed; - // result = flipflopContext.Data; - // } - // } - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance, parameters); - // } - // } - // context.SetFlowData(result); - // } - // return result; - //} - #endregion - - - - - } -} diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index d21c12d..707efdb 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -10,18 +10,9 @@ - - - - - - - - - - + diff --git a/Library/Utils/SereinIoc.cs b/Library/Utils/SereinIoc.cs index d05bea0..2093198 100644 --- a/Library/Utils/SereinIoc.cs +++ b/Library/Utils/SereinIoc.cs @@ -8,55 +8,84 @@ using System.Reflection; namespace Serein.Library.Utils { - + /// + /// IOC管理容器 + /// public class SereinIoc : ISereinIoc { - + /// + /// 实例集合 + /// private readonly ConcurrentDictionary _dependencies; + /// + /// 未完成注入的实例集合。 + /// 键:需要的类型名称 + /// 值:对象实例(存储对象) + /// + private readonly ConcurrentDictionary> _unfinishedDependencies; + + /// + /// 类型集合 + /// private readonly ConcurrentDictionary _typeMappings; + /// + /// 待实例化的类型 + /// private readonly List _waitingForInstantiation; public SereinIoc() { - + // 首先注册自己 _dependencies = new ConcurrentDictionary { [typeof(ISereinIoc).FullName] = this }; - - _typeMappings = new ConcurrentDictionary(); + _typeMappings = new ConcurrentDictionary + { + [typeof(ISereinIoc).FullName] = typeof(ISereinIoc) + }; + _unfinishedDependencies = new ConcurrentDictionary>(); _waitingForInstantiation = new List(); } + /// + /// 获取或创建实例对象(不注入对象的依赖项) + /// + /// 目标类型 + /// 构造函数的参数 + /// public object GetOrCreateServiceInstance(Type type, params object[] parameters) { - Register(type); - object instance; - if (_dependencies.ContainsKey(type.FullName)) { - instance = _dependencies[type.FullName]; + return _dependencies[type.FullName]; } else { - - instance = Activator.CreateInstance(type); - - - _dependencies[type.FullName] = instance; - + var instance = Activator.CreateInstance(type); // 创建目标类型的实例对象 + InjectDependencies(instance);// 注入目标对象的依赖项 + _dependencies[type.FullName] = instance; // 记录实例 + return instance; } - - - return instance; - } - public T CreateServiceInstance(params object[] parameters) + + /// + /// 泛型方法, 获取或创建实例对象(不注入对象的依赖项) + /// + /// 目标类型 + /// 构造函数的参数 + /// + public T GetOrCreateServiceInstance(params object[] parameters) { return (T)GetOrCreateServiceInstance(typeof(T), parameters); } + /// + /// 清空容器对象 + /// + /// public ISereinIoc Reset() { + // 检查是否存在非托管资源 foreach(var instancei in _dependencies.Values) { if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable) @@ -64,54 +93,52 @@ namespace Serein.Library.Utils disposable.Dispose(); } } + _typeMappings.Clear(); _dependencies.Clear(); _waitingForInstantiation.Clear(); - //_typeMappings.Clear(); return this; } - public ISereinIoc RegisterInstantiate(object instantiate) - { - //var type = instantiate.GetType(); - if (!_typeMappings.TryGetValue(instantiate.GetType().FullName,out var type)) - { - _typeMappings[type.FullName] = type; - } - - if(!_dependencies.TryGetValue(type.FullName, out var instancei)) - { - _dependencies[type.FullName] = Activator.CreateInstance(type); - } - // _dependencies.AddOrUpdate(type.FullName,s => instantiate, (s,o) => instantiate); - return this; - } + /// + /// 注册类型 + /// + /// 目标类型 + /// 参数 public ISereinIoc Register(Type type, params object[] parameters) { - - if (!_typeMappings.ContainsKey(type.FullName)) - { - _typeMappings[type.FullName] = type; - } - + RegisterType(type.FullName, type); return this; } + /// + /// 注册类型 + /// + /// 目标类型 + /// 参数 public ISereinIoc Register(params object[] parameters) { - Register(typeof(T), parameters); + var type = typeof(T); + RegisterType(type.FullName, type); return this; } + public ISereinIoc Register(params object[] parameters) where TImplementation : TService { - _typeMappings[typeof(TService).FullName] = typeof(TImplementation); + var typeFullName = typeof(TService).FullName; + RegisterType(typeFullName, typeof(TImplementation)); return this; } + + + /// + /// 注册 + /// + /// + /// public object GetOrInstantiate(Type type) { - - if (!_dependencies.TryGetValue(type.FullName, out object value)) { Register(type); @@ -127,47 +154,57 @@ namespace Serein.Library.Utils } - public T GetOrInstantiate() { if(!_dependencies.TryGetValue(typeof(T).FullName, out object value)) { - Register(); - + Register(typeof(T)); value = Instantiate(typeof(T)); } return (T)value; //throw new InvalidOperationException("目标类型未创建实例"); } + + /// + /// 实例化所有已注册的类型,并尝试绑定 + /// + /// public ISereinIoc Build() { - // 遍历已注册类型 - foreach (var type in _typeMappings.Values) + foreach (var type in _typeMappings.Values.ToArray()) { - // 如果没有创建实例,则创建对应的实例 - if(!_dependencies.ContainsKey(type.FullName)) + + if(_dependencies.ContainsKey(type.FullName)) { - _dependencies[type.FullName] = Activator.CreateInstance(type); + // 已经存在实例,不用管 } + else + { + // 如果没有创建实例,则创建对应的实例 + _dependencies[type.FullName] = CreateInstance(type); + } + // 移除类型的注册记录 + _typeMappings.TryRemove(type.FullName,out _); } // 注入实例的依赖项 foreach (var instance in _dependencies.Values) { - InjectDependencies(instance); // 替换占位符 + InjectDependencies(instance); } //var instance = Instantiate(item.Value); - TryInstantiateWaitingDependencies(); + // TryInstantiateWaitingDependencies(); + return this; } public object Instantiate(Type controllerType, params object[] parameters) { - var instance = Activator.CreateInstance(controllerType, parameters); + var instance = CreateInstance(controllerType, parameters); if(instance != null) { InjectDependencies(instance); @@ -175,23 +212,82 @@ namespace Serein.Library.Utils return instance; } - private void InjectDependencies(object instance) + + + /// + /// 注册类型 + /// + /// + /// + private void RegisterType(string typeFull, Type type) { - var properties = instance.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).ToArray() - .Where(p => p.CanWrite && p.GetCustomAttribute() != null); - - foreach (var property in properties) + if (!_typeMappings.ContainsKey(typeFull)) { - var propertyType = property.PropertyType; - - if (_dependencies.TryGetValue(propertyType.FullName, out var dependencyInstance)) - { - property.SetValue(instance, dependencyInstance); - } - + _typeMappings[typeFull] = type; } } + /// + /// 创建实例时,尝试注入到由ioc容器管理、并需要此实例的对象。 + /// + private object CreateInstance(Type type, params object[] parameters) + { + var instance = Activator.CreateInstance(type); + if(_unfinishedDependencies.TryGetValue(type.FullName, out var unfinishedPropertyList)) + { + foreach ((object obj, PropertyInfo property) in unfinishedPropertyList) + { + property.SetValue(obj, instance); //注入依赖项 + } + + if(_unfinishedDependencies.TryRemove(type.FullName, out unfinishedPropertyList)) + { + unfinishedPropertyList.Clear(); + } + } + return instance; + } + + + /// + /// 注入目标实例的依赖项 + /// + /// + private bool InjectDependencies(object instance) + { + var properties = instance.GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.Public).ToArray() + .Where(p => p.CanWrite // 可写属性 + && p.GetCustomAttribute() != null // 有特性标注需要注入 + && p.GetValue(instance) == null); // 属性为空 + var isPass = true; + foreach (var property in properties) + { + var propertyType = property.PropertyType; + // 通过属性类型名称从ioc容器中获取对应的实例 + if (_dependencies.TryGetValue(propertyType.FullName, out var dependencyInstance)) + { + property.SetValue(instance, dependencyInstance); // 尝试写入到目标实例的属性中 + } + else + { + // 存在依赖项,但目标类型的实例暂未加载,需要等待需要实例完成注册 + var unfinishedDependenciesList = _unfinishedDependencies.GetOrAdd(propertyType.FullName, _ = new List<(object, PropertyInfo)>()); + var data = (instance, property); + if (!unfinishedDependenciesList.Contains(data)) + { + unfinishedDependenciesList.Add(data); + } + isPass = false; + } + } + return isPass; + } + + + /// + /// 再次尝试注入目标实例的依赖项 + /// private void TryInstantiateWaitingDependencies() { foreach (var waitingType in _waitingForInstantiation.ToList()) diff --git a/Library/Utils/SerinExpression/ConditionResolver.cs b/Library/Utils/SerinExpression/ConditionResolver.cs deleted file mode 100644 index 70cda34..0000000 --- a/Library/Utils/SerinExpression/ConditionResolver.cs +++ /dev/null @@ -1,338 +0,0 @@ -using System; -using System.Reflection; - -namespace Serein.NodeFlow.Tool.SerinExpression -{ - /// - /// 条件解析抽象类 - /// - public abstract class ConditionResolver - { - public abstract bool Evaluate(object obj); - } - - public class PassConditionResolver : ConditionResolver - { - public Operator Op { get; set; } - public override bool Evaluate(object obj) - { - return Op switch - { - Operator.Pass => true, - Operator.NotPass => false, - _ => throw new NotSupportedException("不支持的条件类型") - }; - } - - public enum Operator - { - Pass, - NotPass, - } - - } - - public class ValueTypeConditionResolver : ConditionResolver where T : struct, IComparable - { - public enum Operator - { - /// - /// 不进行任何操作 - /// - Node, - /// - /// 大于 - /// - GreaterThan, - /// - /// 小于 - /// - LessThan, - /// - /// 等于 - /// - Equal, - /// - /// 大于或等于 - /// - GreaterThanOrEqual, - /// - /// 小于或等于 - /// - LessThanOrEqual, - /// - /// 在两者之间 - /// - InRange, - /// - /// 不在两者之间 - /// - OutOfRange - } - - public Operator Op { get; set; } - public T Value { get; set; } - public T RangeStart { get; set; } - public T RangeEnd { get; set; } - - public string ArithmeticExpression { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is T typedObj) - { - double numericValue = Convert.ToDouble(typedObj); - if (!string.IsNullOrEmpty(ArithmeticExpression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(ArithmeticExpression, numericValue); - } - - T evaluatedValue = (T)Convert.ChangeType(numericValue, typeof(T)); - - return Op switch - { - Operator.GreaterThan => evaluatedValue.CompareTo(Value) > 0, - Operator.LessThan => evaluatedValue.CompareTo(Value) < 0, - Operator.Equal => evaluatedValue.CompareTo(Value) == 0, - Operator.GreaterThanOrEqual => evaluatedValue.CompareTo(Value) >= 0, - Operator.LessThanOrEqual => evaluatedValue.CompareTo(Value) <= 0, - Operator.InRange => evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0, - Operator.OutOfRange => evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0, - _ => throw new NotSupportedException("不支持的条件类型") - }; - /* switch (Op) - { - case Operator.GreaterThan: - return evaluatedValue.CompareTo(Value) > 0; - case Operator.LessThan: - return evaluatedValue.CompareTo(Value) < 0; - case Operator.Equal: - return evaluatedValue.CompareTo(Value) == 0; - case Operator.GreaterThanOrEqual: - return evaluatedValue.CompareTo(Value) >= 0; - case Operator.LessThanOrEqual: - return evaluatedValue.CompareTo(Value) <= 0; - case Operator.InRange: - return evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0; - case Operator.OutOfRange: - return evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0; - }*/ - } - return false; - } - } - - public class BoolConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 是 - /// - Is - } - - public Operator Op { get; set; } - public bool Value { get; set; } - - public override bool Evaluate(object obj) - { - - if (obj is bool boolObj) - { - return boolObj == Value; - /*switch (Op) - { - case Operator.Is: - return boolObj == Value; - }*/ - } - return false; - } - } - - public class StringConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 出现过 - /// - Contains, - /// - /// 没有出现过 - /// - DoesNotContain, - /// - /// 相等 - /// - Equal, - /// - /// 不相等 - /// - NotEqual, - /// - /// 起始字符串等于 - /// - StartsWith, - /// - /// 结束字符串等于 - /// - EndsWith - } - - public Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is string strObj) - { - return Op switch - { - Operator.Contains => strObj.Contains(Value), - Operator.DoesNotContain => !strObj.Contains(Value), - Operator.Equal => strObj == Value, - Operator.NotEqual => strObj != Value, - Operator.StartsWith => strObj.StartsWith(Value), - Operator.EndsWith => strObj.EndsWith(Value), - _ => throw new NotSupportedException("不支持的条件类型"), - }; - - /* switch (Op) - { - case Operator.Contains: - return strObj.Contains(Value); - case Operator.DoesNotContain: - return !strObj.Contains(Value); - case Operator.Equal: - return strObj == Value; - case Operator.NotEqual: - return strObj != Value; - case Operator.StartsWith: - return strObj.StartsWith(Value); - case Operator.EndsWith: - return strObj.EndsWith(Value); - }*/ - } - return false; - } - } - public class MemberConditionResolver : ConditionResolver where T : struct, IComparable - { - //public string MemberPath { get; set; } - public ValueTypeConditionResolver.Operator Op { get; set; } - public object? TargetObj { get; set; } - public T Value { get; set; } - - public string ArithmeticExpression { get; set; } - - public override bool Evaluate(object? obj) - { - //object? memberValue = GetMemberValue(obj, MemberPath); - if (TargetObj is T typedObj) - { - return new ValueTypeConditionResolver - { - Op = Op, - Value = Value, - ArithmeticExpression = ArithmeticExpression, - }.Evaluate(typedObj); - } - return false; - } - - //private object? GetMemberValue(object? obj, string memberPath) - //{ - // string[] members = memberPath[1..].Split('.'); - // foreach (var member in members) - // { - // if (obj == null) return null; - // Type type = obj.GetType(); - // PropertyInfo? propertyInfo = type.GetProperty(member); - // FieldInfo? fieldInfo = type.GetField(member); - // if (propertyInfo != null) - // obj = propertyInfo.GetValue(obj); - // else if (fieldInfo != null) - // obj = fieldInfo.GetValue(obj); - // else - // throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - // } - // return obj; - //} - } - - public class MemberStringConditionResolver : ConditionResolver - { - - public string MemberPath { get; set; } - - public StringConditionResolver.Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - object memberValue = GetMemberValue(obj, MemberPath); - if (memberValue is string strObj) - { - return new StringConditionResolver - { - Op = Op, - Value = Value - }.Evaluate(strObj); - } - return false; - } - - private object GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - - if (obj == null) return null; - - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - - return obj; - - } - - - - - - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - - - - - - } - -} diff --git a/Library/Utils/SerinExpression/SerinExpressionEvaluator.cs b/Library/Utils/SerinExpression/SerinExpressionEvaluator.cs deleted file mode 100644 index 99666ea..0000000 --- a/Library/Utils/SerinExpression/SerinExpressionEvaluator.cs +++ /dev/null @@ -1,216 +0,0 @@ -using System.Data; - -namespace Serein.NodeFlow.Tool.SerinExpression -{ - public class SerinArithmeticExpressionEvaluator - { - private static readonly DataTable table = new DataTable(); - - public static double Evaluate(string expression, double inputValue) - { - // 替换占位符@为输入值 - expression = expression.Replace("@", inputValue.ToString()); - try - { - // 使用 DataTable.Compute 方法计算表达式 - var result = table.Compute(expression, string.Empty); - return Convert.ToDouble(result); - } - catch - { - throw new ArgumentException("Invalid arithmetic expression."); - } - } - } - - public class SerinExpressionEvaluator - { - /// - /// - /// - /// 表达式 - /// 操作对象 - /// 是否改变了对象(get语法) - /// - /// - /// - public static object Evaluate(string expression, object targetObJ, out bool isChange) - { - var parts = expression.Split([' '], 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid expression format."); - } - - var operation = parts[0].ToLower(); - var operand = parts[1][0] == '.' ? parts[1][1..] : parts[1]; - - var result = operation switch - { - "@num" => ComputedNumber(targetObJ, operand), - "@call" => InvokeMethod(targetObJ, operand), - "@get" => GetMember(targetObJ, operand), - "@set" => SetMember(targetObJ, operand), - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - isChange = operation switch - { - "@num" => true, - "@call" => true, - "@get" => true, - "@set" => false, - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - return result; - } - - - private static readonly char[] separator = ['(', ')']; - private static readonly char[] separatorArray = [',']; - - private static object InvokeMethod(object target, string methodCall) - { - var methodParts = methodCall.Split(separator, StringSplitOptions.RemoveEmptyEntries); - if (methodParts.Length != 2) - { - throw new ArgumentException("Invalid method call format."); - } - - var methodName = methodParts[0]; - var parameterList = methodParts[1]; - var parameters = parameterList.Split(separatorArray, StringSplitOptions.RemoveEmptyEntries) - .Select(p => p.Trim()) - .ToArray(); - - var method = target.GetType().GetMethod(methodName); - if (method == null) - { - throw new ArgumentException($"Method {methodName} not found on target."); - } - - var parameterValues = method.GetParameters() - .Select((p, index) => Convert.ChangeType(parameters[index], p.ParameterType)) - .ToArray(); - - - return method.Invoke(target, parameterValues); - - } - - private static object GetMember(object target, string memberPath) - { - var members = memberPath.Split('.'); - foreach (var member in members) - { - - if (target == null) return null; - - - var property = target.GetType().GetProperty(member); - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - - return target; - - } - - private static object SetMember(object target, string assignment) - { - var parts = assignment.Split(new[] { '=' }, 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid assignment format."); - } - - var memberPath = parts[0].Trim(); - var value = parts[1].Trim(); - - var members = memberPath.Split('.'); - for (int i = 0; i < members.Length - 1; i++) - { - var member = members[i]; - - var property = target.GetType().GetProperty(member); - - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - var lastMember = members.Last(); - - var lastProperty = target.GetType().GetProperty(lastMember); - - if (lastProperty != null) - { - var convertedValue = Convert.ChangeType(value, lastProperty.PropertyType); - lastProperty.SetValue(target, convertedValue); - } - else - { - var lastField = target.GetType().GetField(lastMember); - if (lastField != null) - { - var convertedValue = Convert.ChangeType(value, lastField.FieldType); - lastField.SetValue(target, convertedValue); - } - else - { - throw new ArgumentException($"Member {lastMember} not found on target."); - } - } - - return target; - } - - private static double ComputedNumber(object value, string expression) - { - double numericValue = Convert.ToDouble(value); - if (!string.IsNullOrEmpty(expression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(expression, numericValue); - } - - return numericValue; - } - } -} diff --git a/NodeFlow/Base/NodeModelBaseFunc.cs b/NodeFlow/Base/NodeModelBaseFunc.cs index c678ad0..9a37fad 100644 --- a/NodeFlow/Base/NodeModelBaseFunc.cs +++ b/NodeFlow/Base/NodeModelBaseFunc.cs @@ -3,7 +3,7 @@ using Serein.Library.Api; using Serein.Library.Entity; using Serein.Library.Enums; using Serein.Library.Ex; -using Serein.NodeFlow.Tool.SerinExpression; +using Serein.NodeFlow.Tool.SereinExpression; using System; using System.Collections.Generic; using System.Linq; diff --git a/NodeFlow/ConnectionType.cs b/NodeFlow/ConnectionType.cs deleted file mode 100644 index 1c8d050..0000000 --- a/NodeFlow/ConnectionType.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.NodeFlow -{ - public enum ConnectionType - { - /// - /// 真分支 - /// - IsSucceed, - /// - /// 假分支 - /// - IsFail, - /// - /// 异常发生分支 - /// - IsError, - /// - /// 上游分支(执行当前节点前会执行一次上游分支) - /// - Upstream, - } - - -} diff --git a/NodeFlow/DynamicContext.cs b/NodeFlow/DynamicContext.cs deleted file mode 100644 index 732e26c..0000000 --- a/NodeFlow/DynamicContext.cs +++ /dev/null @@ -1,230 +0,0 @@ - -using Serein.NodeFlow.Model; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using static System.Collections.Specialized.BitVector32; -using static System.Runtime.InteropServices.JavaScript.JSType; - -namespace Serein.NodeFlow -{ - - //public enum FfState - //{ - // Succeed, - // Cancel, - // Error, - //} - - //public class FlipflopContext - //{ - // public FlowStateType State { get; set; } - // public object? Data { get; set; } - // public FlipflopContext(FlowStateType ffState, object? data = null) - // { - // State = ffState; - // Data = data; - // } - //} - - public static class FlipflopFunc - { - /// - /// 传入触发器方法的返回类型,尝试获取Task[Flipflop[]] 中的泛型类型 - /// - //public static Type GetFlipflopInnerType(Type type) - //{ - // // 检查是否为泛型类型且为 Task<> - // if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>)) - // { - // // 获取 Task<> 的泛型参数类型,即 Flipflop<> - // var innerType = type.GetGenericArguments()[0]; - - // // 检查泛型参数是否为 Flipflop<> - // if (innerType.IsGenericType && innerType.GetGenericTypeDefinition() == typeof(FlipflopContext<>)) - // { - // // 获取 Flipflop<> 的泛型参数类型,即 T - // var flipflopInnerType = innerType.GetGenericArguments()[0]; - - // // 返回 Flipflop<> 中的具体类型 - // return flipflopInnerType; - // } - // } - // // 如果不符合条件,返回 null - // return null; - //} - - public static bool IsTaskOfFlipflop(Type type) - { - // 检查是否为泛型类型且为 Task<> - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>)) - { - // 获取 Task<> 的泛型参数类型 - var innerType = type.GetGenericArguments()[0]; - - // 检查泛型参数是否为 Flipflop<> - if (innerType == typeof(FlipflopContext)) - //if (innerType.IsGenericType && innerType.GetGenericTypeDefinition() == typeof(FlipflopContext<>)) - { - return true; - } - } - - return false; - } - } - - /// - /// 触发器上下文 - /// - public class FlipflopContext// - { - public LibraryCore.NodeFlow.FlowStateType State { get; set; } - //public TResult? Data { get; set; } - public object? Data { get; set; } - public FlipflopContext(FlowStateType ffState) - { - State = ffState; - } - public FlipflopContext(FlowStateType ffState, object data) - { - State = ffState; - Data = data; - } - - - } - - /// - /// 动态流程上下文 - /// - - public class DynamicContext(ISereinIoc serviceContainer) - - { - - private readonly string contextGuid = "";//System.Guid.NewGuid().ToString(); - - public ISereinIoc ServiceContainer { get; } = serviceContainer; - private List InitServices { get; set; } = []; - - // private ConcurrentDictionary ContextData { get; set; } = []; - - //public void SetFlowData(object data) - //{ - // var threadId = Thread.CurrentThread.ManagedThreadId.ToString(); - // var name = $"{threadId}.{contextGuid}FlowData"; - // SetData(name,data); - //} - //public object GetFlowData(bool IsRetain = false) - //{ - // var threadId = Thread.CurrentThread.ManagedThreadId.ToString(); - // var name = $"{threadId}.{contextGuid}FlowData"; - // if (IsRetain) - // { - // return GetData(name); - // } - // else - // { - // return GetAndRemoteData(name); - - // } - //} - - - public void InitService() - { - InitService(typeof(T)); - } - public void InitService(Type type) - { - if (!InitServices.Contains(type)) - { - InitServices.Add(type); - } - else - { - //throw new Exception("初始化时试图添加已存在的类型:"+type.Name); - Console.WriteLine("初始化时试图添加已存在的类型:" + type.Name); - } - } - public void Biuld() - { - foreach (var item in InitServices) - { - ServiceContainer.Register(item); - } - ServiceContainer.Build(); - } - - //public object? RemoveData(string key) - //{ - // if (ContextData.Remove(key, out var data)) - // { - // return data; - // } - // return null; - //} - - //public void SetData(string key, T value) - //{ - // ContextData[key] = value; - //} - - //public T? GetData(string key) - //{ - // if (ContextData.TryGetValue(key, out object? value)) - // { - // if(value == null) - // { - // return default; - // } - // if (value.GetType() == typeof(T)) - // { - // return (T)value; - // } - - // } - // return default; - //} - - //public object? GetData(string key) - //{ - // if (ContextData.TryGetValue(key, out object? value)) - // { - // return value; - // } - // return null; - //} - - - //public ConcurrentDictionary FlipFlopTasks { get; set; } = []; - - public NodeRunTcs NodeRunCts { get; set; } - public Task CreateTimingTask(Action action, int time = 100, int count = -1) - { - NodeRunCts ??= ServiceContainer.GetOrInstantiate(); - return Task.Factory.StartNew(async () => - { - for (int i = 0; i < count; i++) - { - NodeRunCts.Token.ThrowIfCancellationRequested(); - await Task.Delay(time); - action.Invoke(); - } - }); - } - } - - public static class MyExtensions - { - public static TaskAwaiter GetAwaiter(this int i) => Task.Delay(i).GetAwaiter(); - } - - - // if (time <= 0) throw new ArgumentException("时间不能≤0"); -} diff --git a/NodeFlow/FlowEnvironment.cs b/NodeFlow/FlowEnvironment.cs index b3a030b..0b9a7e4 100644 --- a/NodeFlow/FlowEnvironment.cs +++ b/NodeFlow/FlowEnvironment.cs @@ -90,7 +90,7 @@ namespace Serein.NodeFlow public List MethodDetailss { get; } = []; - public Dictionary Nodes { get; } = []; + public Dictionary Nodes { get; } = []; public List Regions { get; } = []; @@ -104,13 +104,15 @@ namespace Serein.NodeFlow /// /// 起始节点 /// - public NodeModelBase StartNode { - get - { + public NodeModelBase StartNode + { + get + { return _startNode; } - set { - if(_startNode is null) + set + { + if (_startNode is null) { value.IsStart = true; _startNode = value; @@ -121,7 +123,8 @@ namespace Serein.NodeFlow value.IsStart = true; _startNode = value; } - } } + } + } /// /// 异步运行 @@ -165,7 +168,7 @@ namespace Serein.NodeFlow public bool TryGetMethodDetails(string name, out MethodDetails? md) { md = MethodDetailss.FirstOrDefault(it => it.MethodName == name); - if(md == null) + if (md == null) { return false; } @@ -187,7 +190,7 @@ namespace Serein.NodeFlow foreach (var dll in dllPaths) { var dllFilePath = System.IO.Path.GetFullPath(System.IO.Path.Combine(filePath, dll)); - (var assembly, var list) = LoadAssembly(dllFilePath); + (var assembly, var list) = LoadAssembly(dllFilePath); if (assembly is not null && list.Count > 0) { methodDetailss.AddRange(methodDetailss); // 暂存方法描述 @@ -195,7 +198,7 @@ namespace Serein.NodeFlow } } // 方法加载完成,缓存到运行环境中。 - MethodDetailss.AddRange(methodDetailss); + MethodDetailss.AddRange(methodDetailss); methodDetailss.Clear(); @@ -216,7 +219,7 @@ namespace Serein.NodeFlow // 不存在对应的起始节点 continue; } - + List<(ConnectionType, string[])> nodeGuids = [(ConnectionType.IsSucceed,nodeInfo.TrueNodes), (ConnectionType.IsFail, nodeInfo.FalseNodes), @@ -256,10 +259,10 @@ namespace Serein.NodeFlow { return; } - if(fromNode is null || toNode is null) + if (fromNode is null || toNode is null) { - return ; - } + return; + } // 开始连接 ConnectNode(fromNode, toNode, connectionType); // 外部调用连接方法 @@ -282,7 +285,7 @@ namespace Serein.NodeFlow NodeControlType.ConditionRegion => typeof(CompositeConditionNode), _ => null }; - if(nodeType == null) + if (nodeType == null) { return; } @@ -305,7 +308,7 @@ namespace Serein.NodeFlow Nodes[nodeBase.Guid] = nodeBase; // 如果是触发器,则需要添加到专属集合中 - if (nodeControlType == NodeControlType.Flipflop && nodeBase is SingleFlipflopNode flipflopNode ) + if (nodeControlType == NodeControlType.Flipflop && nodeBase is SingleFlipflopNode flipflopNode) { var guid = flipflopNode.Guid; if (!FlipflopNodes.Exists(it => it.Guid.Equals(guid))) @@ -313,7 +316,7 @@ namespace Serein.NodeFlow FlipflopNodes.Add(flipflopNode); } } - + // 通知UI更改 OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeBase)); // 因为需要UI先布置了元素,才能通知UI变更特效 @@ -338,7 +341,7 @@ namespace Serein.NodeFlow MethodDetailss.AddRange(list); OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list)); } - + } /// @@ -383,7 +386,7 @@ namespace Serein.NodeFlow NodeConnectChangeEventArgs.ChangeTypeEnum.Remote)); } - /// + /// /// 移除节点 /// /// @@ -402,10 +405,10 @@ namespace Serein.NodeFlow { return; } - + // 遍历所有父节点,从那些父节点中的子节点集合移除该节点 - foreach(var pnc in remoteNode.PreviousNodes) + foreach (var pnc in remoteNode.PreviousNodes) { var pCType = pnc.Key; // 连接类型 for (int i = 0; i < pnc.Value.Count; i++) @@ -446,9 +449,9 @@ namespace Serein.NodeFlow /// public void SetStartNode(string newNodeGuid) { - if(Nodes.TryGetValue(newNodeGuid, out NodeModelBase? newStartNodeModel)) + if (Nodes.TryGetValue(newNodeGuid, out NodeModelBase? newStartNodeModel)) { - if(newStartNodeModel != null) + if (newStartNodeModel != null) { SetStartNode(newStartNodeModel); //var oldNodeGuid = ""; @@ -491,7 +494,7 @@ namespace Serein.NodeFlow { // 加载DLL,创建 MethodDetails、实例作用对象、委托方法 var itemMethodDetails = MethodDetailsHelperTmp.GetList(item, false); - foreach(var md in itemMethodDetails) + foreach (var md in itemMethodDetails) { // var instanceType = // Activator.CreateInstance(md.ActingInstanceType); @@ -599,16 +602,7 @@ namespace Serein.NodeFlow #endregion - - - - - - - - - } - +} public static class FlowFunc { public static Library.Entity.Library ToLibrary(this Assembly assembly) diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs index 15815c1..8943f31 100644 --- a/NodeFlow/FlowStarter.cs +++ b/NodeFlow/FlowStarter.cs @@ -50,7 +50,7 @@ namespace Serein.NodeFlow Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIoc, flowEnvironment); } - MainCts = SereinIoc.CreateServiceInstance(); + MainCts = SereinIoc.GetOrCreateServiceInstance(); foreach (var md in methodDetailss) { diff --git a/NodeFlow/MethodDetails.cs b/NodeFlow/MethodDetails.cs deleted file mode 100644 index 1da2138..0000000 --- a/NodeFlow/MethodDetails.cs +++ /dev/null @@ -1,241 +0,0 @@ -using Serein.Library.Api; -using Serein.Library.Enums; - -namespace Serein.NodeFlow -{ - - - /// - /// 显式参数 - /// - public class ExplicitData - { - /// - /// 索引 - /// - public int Index { get; set; } - /// - /// 是否为显式参数 - /// - public bool IsExplicitData { get; set; } - /// - /// 显式类型 - /// - public Type? ExplicitType { get; set; } - - /// - /// 显示类型编号> - /// - public string ExplicitTypeName { get; set; } - - /// - /// 方法需要的类型 - /// - public Type DataType { get; set; } - - /// - /// 方法入参参数名称 - /// - public string ParameterName { get; set; } - - /// - /// 入参值 - /// - - public string DataValue { get; set; } - - - - public string[] Items { get; set; } - - - - - public ExplicitData Clone() => new() - { - Index = Index, - IsExplicitData = IsExplicitData, - ExplicitType = ExplicitType, - DataType = DataType, - ParameterName = ParameterName, - ExplicitTypeName = ExplicitTypeName, - DataValue = string.IsNullOrEmpty(DataValue) ? string.Empty : DataValue, - Items = [.. Items], - }; - } - - - - public class MethodDetails : IMethodDetails - { - /// - /// 拷贝 - /// - /// - public MethodDetails Clone() - { - return new MethodDetails - { - ActingInstance = ActingInstance, - ActingInstanceType = ActingInstanceType, - MethodDelegate = MethodDelegate, - MethodDynamicType = MethodDynamicType, - MethodGuid = Guid.NewGuid().ToString(), - MethodTips = MethodTips, - ReturnType = ReturnType, - MethodName = MethodName, - MethodLockName = MethodLockName, - IsNetFramework = IsNetFramework, - ExplicitDatas = ExplicitDatas.Select(it => it.Clone()).ToArray(), - }; - } - - /// - /// 作用实例 - /// - - public Type ActingInstanceType { get; set; } - - /// - /// 作用实例 - /// - - public object ActingInstance { get; set; } - - /// - /// 方法GUID - /// - - public string MethodGuid { get; set; } - - /// - /// 方法名称 - /// - - public string MethodName { get; set; } - - /// - /// 方法委托 - /// - - public Delegate MethodDelegate { get; set; } - - /// - /// 节点类型 - /// - public NodeType MethodDynamicType { get; set; } - /// - /// 锁名称 - /// - - public string MethodLockName { get; set; } - - - /// - /// 方法说明 - /// - - public string MethodTips { get; set; } - - - /// - /// 参数内容 - /// - - public ExplicitData[] ExplicitDatas { get; set; } - - /// - /// 出参类型 - /// - - public Type ReturnType { get; set; } - - public bool IsNetFramework { get; set; } - - - - - - //public bool IsCanConnect(Type returnType) - //{ - // if (ExplicitDatas.Length == 0) - // { - // // 目标不需要传参,可以舍弃结果? - // return true; - // } - // var types = ExplicitDatas.Select(it => it.DataType).ToArray(); - // // 检查返回类型是否是元组类型 - // if (returnType.IsGenericType && IsValueTuple(returnType)) - // { - - // return CompareGenericArguments(returnType, types); - // } - // else - // { - // int index = 0; - // if (types[index] == typeof(DynamicContext)) - // { - // index++; - // if (types.Length == 1) - // { - // return true; - // } - // } - // // 被连接节点检查自己需要的参数类型,与发起连接的节点比较返回值类型 - // if (returnType == types[index]) - // { - // return true; - // } - // } - // return false; - //} - - ///// - ///// 检查元组类型 - ///// - ///// - ///// - //private bool IsValueTuple(Type type) - //{ - // if (!type.IsGenericType) return false; - - // var genericTypeDef = type.GetGenericTypeDefinition(); - // return genericTypeDef == typeof(ValueTuple<>) || - // genericTypeDef == typeof(ValueTuple<,>) || - // genericTypeDef == typeof(ValueTuple<,,>) || - // genericTypeDef == typeof(ValueTuple<,,,>) || - // genericTypeDef == typeof(ValueTuple<,,,,>) || - // genericTypeDef == typeof(ValueTuple<,,,,,>) || - // genericTypeDef == typeof(ValueTuple<,,,,,,>) || - // genericTypeDef == typeof(ValueTuple<,,,,,,,>); - //} - - //private bool CompareGenericArguments(Type returnType, Type[] parameterTypes) - //{ - // var genericArguments = returnType.GetGenericArguments(); - // var length = parameterTypes.Length; - - // for (int i = 0; i < genericArguments.Length; i++) - // { - // if (i >= length) return false; - - // if (IsValueTuple(genericArguments[i])) - // { - // // 如果当前参数也是 ValueTuple,递归检查嵌套的泛型参数 - // if (!CompareGenericArguments(genericArguments[i], parameterTypes.Skip(i).ToArray())) - // { - // return false; - // } - // } - // else if (genericArguments[i] != parameterTypes[i]) - // { - // return false; - // } - // } - - // return true; - //} - } - - -} diff --git a/NodeFlow/Model/SingleConditionNode.cs b/NodeFlow/Model/SingleConditionNode.cs index cba95de..6b4c047 100644 --- a/NodeFlow/Model/SingleConditionNode.cs +++ b/NodeFlow/Model/SingleConditionNode.cs @@ -3,7 +3,7 @@ using Serein.Library.Api; using Serein.Library.Entity; using Serein.Library.Enums; using Serein.NodeFlow.Base; -using Serein.NodeFlow.Tool.SerinExpression; +using Serein.NodeFlow.Tool.SereinExpression; namespace Serein.NodeFlow.Model { @@ -42,7 +42,7 @@ namespace Serein.NodeFlow.Model } try { - var isPass = SerinConditionParser.To(result, Expression); + var isPass = SereinConditionParser.To(result, Expression); NextOrientation = isPass ? ConnectionType.IsSucceed : ConnectionType.IsFail; } catch (Exception ex) diff --git a/NodeFlow/Model/SingleExpOpNode.cs b/NodeFlow/Model/SingleExpOpNode.cs index 7953401..88d0753 100644 --- a/NodeFlow/Model/SingleExpOpNode.cs +++ b/NodeFlow/Model/SingleExpOpNode.cs @@ -2,7 +2,7 @@ using Serein.Library.Entity; using Serein.Library.Enums; using Serein.NodeFlow.Base; -using Serein.NodeFlow.Tool.SerinExpression; +using Serein.NodeFlow.Tool.SereinExpression; using System.Text; namespace Serein.NodeFlow.Model diff --git a/NodeFlow/SerinExpression/ConditionResolver.cs b/NodeFlow/SerinExpression/ConditionResolver.cs deleted file mode 100644 index 8e164aa..0000000 --- a/NodeFlow/SerinExpression/ConditionResolver.cs +++ /dev/null @@ -1,337 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace Serein.NodeFlow.SerinExpression -{ - - public abstract class ConditionResolver - { - public abstract bool Evaluate(object obj); - } - - public class PassConditionResolver : ConditionResolver - { - public Operator Op { get; set; } - public override bool Evaluate(object obj) - { - return Op switch - { - Operator.Pass => true, - Operator.NotPass => false, - _ => throw new NotSupportedException("不支持的条件类型") - }; - } - - public enum Operator - { - Pass, - NotPass, - } - - } - - public class ValueTypeConditionResolver : ConditionResolver where T : struct, IComparable - { - public enum Operator - { - /// - /// 不进行任何操作 - /// - Node, - /// - /// 大于 - /// - GreaterThan, - /// - /// 小于 - /// - LessThan, - /// - /// 等于 - /// - Equal, - /// - /// 大于或等于 - /// - GreaterThanOrEqual, - /// - /// 小于或等于 - /// - LessThanOrEqual, - /// - /// 在两者之间 - /// - InRange, - /// - /// 不在两者之间 - /// - OutOfRange - } - - public Operator Op { get; set; } - public T Value { get; set; } - public T RangeStart { get; set; } - public T RangeEnd { get; set; } - - public string ArithmeticExpression { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is T typedObj) - { - double numericValue = Convert.ToDouble(typedObj); - if (!string.IsNullOrEmpty(ArithmeticExpression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(ArithmeticExpression, numericValue); - } - - T evaluatedValue = (T)Convert.ChangeType(numericValue, typeof(T)); - - return Op switch - { - Operator.GreaterThan => evaluatedValue.CompareTo(Value) > 0, - Operator.LessThan => evaluatedValue.CompareTo(Value) < 0, - Operator.Equal => evaluatedValue.CompareTo(Value) == 0, - Operator.GreaterThanOrEqual => evaluatedValue.CompareTo(Value) >= 0, - Operator.LessThanOrEqual => evaluatedValue.CompareTo(Value) <= 0, - Operator.InRange => evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0, - Operator.OutOfRange => evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0, - _ => throw new NotSupportedException("不支持的条件类型") - }; - /* switch (Op) - { - case Operator.GreaterThan: - return evaluatedValue.CompareTo(Value) > 0; - case Operator.LessThan: - return evaluatedValue.CompareTo(Value) < 0; - case Operator.Equal: - return evaluatedValue.CompareTo(Value) == 0; - case Operator.GreaterThanOrEqual: - return evaluatedValue.CompareTo(Value) >= 0; - case Operator.LessThanOrEqual: - return evaluatedValue.CompareTo(Value) <= 0; - case Operator.InRange: - return evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0; - case Operator.OutOfRange: - return evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0; - }*/ - } - return false; - } - } - - public class BoolConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 是 - /// - Is - } - - public Operator Op { get; set; } - public bool Value { get; set; } - - public override bool Evaluate(object obj) - { - - if (obj is bool boolObj) - { - return boolObj == Value; - /*switch (Op) - { - case Operator.Is: - return boolObj == Value; - }*/ - } - return false; - } - } - - public class StringConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 出现过 - /// - Contains, - /// - /// 没有出现过 - /// - DoesNotContain, - /// - /// 相等 - /// - Equal, - /// - /// 不相等 - /// - NotEqual, - /// - /// 起始字符串等于 - /// - StartsWith, - /// - /// 结束字符串等于 - /// - EndsWith - } - - public Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is string strObj) - { - return Op switch - { - Operator.Contains => strObj.Contains(Value), - Operator.DoesNotContain => !strObj.Contains(Value), - Operator.Equal => strObj == Value, - Operator.NotEqual => strObj != Value, - Operator.StartsWith => strObj.StartsWith(Value), - Operator.EndsWith => strObj.EndsWith(Value), - _ => throw new NotSupportedException("不支持的条件类型"), - }; - - /* switch (Op) - { - case Operator.Contains: - return strObj.Contains(Value); - case Operator.DoesNotContain: - return !strObj.Contains(Value); - case Operator.Equal: - return strObj == Value; - case Operator.NotEqual: - return strObj != Value; - case Operator.StartsWith: - return strObj.StartsWith(Value); - case Operator.EndsWith: - return strObj.EndsWith(Value); - }*/ - } - return false; - } - } - public class MemberConditionResolver : ConditionResolver where T : struct, IComparable - { - //public string MemberPath { get; set; } - public ValueTypeConditionResolver.Operator Op { get; set; } - public object? TargetObj { get; set; } - public T Value { get; set; } - - public string ArithmeticExpression { get; set; } - - public override bool Evaluate(object? obj) - { - //object? memberValue = GetMemberValue(obj, MemberPath); - if (TargetObj is T typedObj) - { - return new ValueTypeConditionResolver - { - Op = Op, - Value = Value, - ArithmeticExpression = ArithmeticExpression, - }.Evaluate(typedObj); - } - return false; - } - - //private object? GetMemberValue(object? obj, string memberPath) - //{ - // string[] members = memberPath[1..].Split('.'); - // foreach (var member in members) - // { - // if (obj == null) return null; - // Type type = obj.GetType(); - // PropertyInfo? propertyInfo = type.GetProperty(member); - // FieldInfo? fieldInfo = type.GetField(member); - // if (propertyInfo != null) - // obj = propertyInfo.GetValue(obj); - // else if (fieldInfo != null) - // obj = fieldInfo.GetValue(obj); - // else - // throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - // } - // return obj; - //} - } - - public class MemberStringConditionResolver : ConditionResolver - { - - public string MemberPath { get; set; } - - public StringConditionResolver.Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - object memberValue = GetMemberValue(obj, MemberPath); - if (memberValue is string strObj) - { - return new StringConditionResolver - { - Op = Op, - Value = Value - }.Evaluate(strObj); - } - return false; - } - - private object GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - - if (obj == null) return null; - - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - - return obj; - - } - - - - - - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - - - - - - } - -} diff --git a/NodeFlow/SerinExpression/SerinConditionParser.cs b/NodeFlow/SerinExpression/SerinConditionParser.cs deleted file mode 100644 index 210c14d..0000000 --- a/NodeFlow/SerinExpression/SerinConditionParser.cs +++ /dev/null @@ -1,329 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Reflection; - -namespace Serein.NodeFlow.SerinExpression; - -public class SerinConditionParser -{ - public static bool To(T data, string expression) - { - try - { - - return ConditionParse(data, expression).Evaluate(data); - - } - catch (Exception ex) - { - Console.WriteLine(ex); - throw; - } - } - - public static ConditionResolver ConditionParse(object data, string expression) - { - if (expression.StartsWith('.') /*&& expression.Contains('<') && expression.Contains('>')*/) - { - return ParseObjectExpression(data, expression); - } - else - { - return ParseSimpleExpression(data, expression); - } - - - bool ContainsArithmeticOperators(string expression) - { - return expression.Contains('+') || expression.Contains('-') || expression.Contains('*') || expression.Contains('/'); - } - - } - - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - private static object? GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - if (obj == null) return null; - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - return obj; - } - - private static ConditionResolver ParseObjectExpression(object data, string expression) - { - var parts = expression.Split(' '); - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - int typeStartIndex = expression.IndexOf('<'); - int typeEndIndex = expression.IndexOf('>'); - - string memberPath; - Type type; - object? targetObj; - if (typeStartIndex + typeStartIndex == -2) - { - memberPath = operatorStr; - targetObj = GetMemberValue(data, operatorStr); - - type = targetObj.GetType(); - - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - if (typeStartIndex >= typeEndIndex) - { - throw new ArgumentException("无效的表达式格式"); - } - memberPath = expression.Substring(0, typeStartIndex).Trim(); - string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1).Trim().ToLower(); - parts = expression.Substring(typeEndIndex + 1).Trim().Split(' '); - if (parts.Length == 3) - { - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - operatorStr = parts[0].ToLower(); - valueStr = string.Join(' ', parts.Skip(1)); - } - targetObj = GetMemberValue(data, memberPath); - - Type? tempType = typeStr switch - { - "int" => typeof(int), - "double" => typeof(double), - "bool" => typeof(bool), - "string" => typeof(string), - _ => Type.GetType(typeStr) - }; - type = tempType ?? throw new ArgumentException("对象表达式无效的类型声明"); - } - - - - if (type == typeof(int)) - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - TargetObj = targetObj, - //MemberPath = memberPath, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - else if (type == typeof(bool)) - { - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = (ValueTypeConditionResolver.Operator)ParseBoolOperator(operatorStr) - }; - } - else if (type == typeof(string)) - { - return new MemberStringConditionResolver - { - MemberPath = memberPath, - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - private static ConditionResolver ParseSimpleExpression(object data, string expression) - { - if ("pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.Pass, - }; - } - else - { - if ("not pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - if ("!pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - } - - - var parts = expression.Split(' '); - - if (parts.Length < 2) - throw new ArgumentException("无效的表达式格式。"); - - //string typeStr = parts[0]; - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - Type type = data.GetType();//Type.GetType(typeStr); - if (type == typeof(int)) - { - var op = ParseValueTypeOperator(operatorStr); - if (op == ValueTypeConditionResolver.Operator.InRange || op == ValueTypeConditionResolver.Operator.OutOfRange) - { - var temp = valueStr.Split('-'); - if (temp.Length < 2) - throw new ArgumentException($"范围无效:{valueStr}。"); - int rangeStart = int.Parse(temp[0], CultureInfo.InvariantCulture); - int rangeEnd = int.Parse(temp[1], CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - RangeStart = rangeStart, - RangeEnd = rangeEnd, - ArithmeticExpression = GetArithmeticExpression(parts[0]), - }; - } - else - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(bool)) - { - bool value = bool.Parse(valueStr); - return new BoolConditionResolver - { - Op = ParseBoolOperator(operatorStr), - Value = value, - }; - } - else if (type == typeof(string)) - { - return new StringConditionResolver - { - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - - private static ValueTypeConditionResolver.Operator ParseValueTypeOperator(string operatorStr) where T : struct, IComparable - { - return operatorStr switch - { - ">" => ValueTypeConditionResolver.Operator.GreaterThan, - "<" => ValueTypeConditionResolver.Operator.LessThan, - "==" => ValueTypeConditionResolver.Operator.Equal, - ">=" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "≥" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "<=" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "≤" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "equals" => ValueTypeConditionResolver.Operator.Equal, - "in" => ValueTypeConditionResolver.Operator.InRange, - "!in" => ValueTypeConditionResolver.Operator.OutOfRange, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for value type.") - }; - } - - private static BoolConditionResolver.Operator ParseBoolOperator(string operatorStr) - { - return operatorStr switch - { - "is" => BoolConditionResolver.Operator.Is, - "==" => BoolConditionResolver.Operator.Is, - "equals" => BoolConditionResolver.Operator.Is, - //"isFalse" => BoolConditionNode.Operator.IsFalse, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for bool type.") - }; - } - - private static StringConditionResolver.Operator ParseStringOperator(string operatorStr) - { - return operatorStr switch - { - "c" => StringConditionResolver.Operator.Contains, - "nc" => StringConditionResolver.Operator.DoesNotContain, - "sw" => StringConditionResolver.Operator.StartsWith, - "ew" => StringConditionResolver.Operator.EndsWith, - - "contains" => StringConditionResolver.Operator.Contains, - "doesNotContain" => StringConditionResolver.Operator.DoesNotContain, - "equals" => StringConditionResolver.Operator.Equal, - "==" => StringConditionResolver.Operator.Equal, - "notEquals" => StringConditionResolver.Operator.NotEqual, - "!=" => StringConditionResolver.Operator.NotEqual, - "startsWith" => StringConditionResolver.Operator.StartsWith, - "endsWith" => StringConditionResolver.Operator.EndsWith, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for string type.") - }; - } -} diff --git a/NodeFlow/SerinExpression/SerinExpressionEvaluator.cs b/NodeFlow/SerinExpression/SerinExpressionEvaluator.cs deleted file mode 100644 index decf1bc..0000000 --- a/NodeFlow/SerinExpression/SerinExpressionEvaluator.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static Serein.NodeFlow.Model.SingleExpOpNode; -using static System.Runtime.InteropServices.JavaScript.JSType; - -namespace Serein.NodeFlow.SerinExpression -{ - public class SerinArithmeticExpressionEvaluator - { - private static readonly DataTable table = new DataTable(); - - public static double Evaluate(string expression, double inputValue) - { - // 替换占位符@为输入值 - expression = expression.Replace("@", inputValue.ToString()); - try - { - // 使用 DataTable.Compute 方法计算表达式 - var result = table.Compute(expression, string.Empty); - return Convert.ToDouble(result); - } - catch - { - throw new ArgumentException("Invalid arithmetic expression."); - } - } - } - - public class SerinExpressionEvaluator - { - public static object Evaluate(string expression, object targetObJ, out bool IsChange) - { - var parts = expression.Split([' '], 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid expression format."); - } - - var operation = parts[0].ToLower(); - var operand = parts[1][0] == '.' ? parts[1][1..] : parts[1]; - - var result = operation switch - { - "@num" => ComputedNumber(targetObJ, operand), - "@call" => InvokeMethod(targetObJ, operand), - "@get" => GetMember(targetObJ, operand), - "@set" => SetMember(targetObJ, operand), - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - IsChange = operation switch - { - "@num" => true, - "@call" => true, - "@get" => true, - "@set" => false, - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - return result; - } - - - private static readonly char[] separator = ['(', ')']; - private static readonly char[] separatorArray = [',']; - - private static object InvokeMethod(object target, string methodCall) - { - var methodParts = methodCall.Split(separator, StringSplitOptions.RemoveEmptyEntries); - if (methodParts.Length != 2) - { - throw new ArgumentException("Invalid method call format."); - } - - var methodName = methodParts[0]; - var parameterList = methodParts[1]; - var parameters = parameterList.Split(separatorArray, StringSplitOptions.RemoveEmptyEntries) - .Select(p => p.Trim()) - .ToArray(); - - var method = target.GetType().GetMethod(methodName); - if (method == null) - { - throw new ArgumentException($"Method {methodName} not found on target."); - } - - var parameterValues = method.GetParameters() - .Select((p, index) => Convert.ChangeType(parameters[index], p.ParameterType)) - .ToArray(); - - - return method.Invoke(target, parameterValues); - - } - - private static object GetMember(object target, string memberPath) - { - var members = memberPath.Split('.'); - foreach (var member in members) - { - - if (target == null) return null; - - - var property = target.GetType().GetProperty(member); - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - - return target; - - } - - private static object SetMember(object target, string assignment) - { - var parts = assignment.Split(new[] { '=' }, 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid assignment format."); - } - - var memberPath = parts[0].Trim(); - var value = parts[1].Trim(); - - var members = memberPath.Split('.'); - for (int i = 0; i < members.Length - 1; i++) - { - var member = members[i]; - - var property = target.GetType().GetProperty(member); - - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - var lastMember = members.Last(); - - var lastProperty = target.GetType().GetProperty(lastMember); - - if (lastProperty != null) - { - var convertedValue = Convert.ChangeType(value, lastProperty.PropertyType); - lastProperty.SetValue(target, convertedValue); - } - else - { - var lastField = target.GetType().GetField(lastMember); - if (lastField != null) - { - var convertedValue = Convert.ChangeType(value, lastField.FieldType); - lastField.SetValue(target, convertedValue); - } - else - { - throw new ArgumentException($"Member {lastMember} not found on target."); - } - } - - return target; - } - - private static double ComputedNumber(object value, string expression) - { - double numericValue = Convert.ToDouble(value); - if (!string.IsNullOrEmpty(expression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(expression, numericValue); - } - - return numericValue; - } - } -} diff --git a/NodeFlow/Tool/Attribute.cs b/NodeFlow/Tool/Attribute.cs deleted file mode 100644 index e6b656f..0000000 --- a/NodeFlow/Tool/Attribute.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.NodeFlow.Tool -{ - - public enum DynamicNodeType - { - /// - /// 初始化 - /// - Init, - /// - /// 开始载入 - /// - Loading, - /// - /// 结束 - /// - Exit, - - /// - /// 触发器 - /// - Flipflop, - /// - /// 条件节点 - /// - Condition, - /// - /// 动作节点 - /// - Action, - } - - - - /// - /// 用来判断一个类是否需要注册并构建实例(单例模式场景使用) - /// - [AttributeUsage(AttributeTargets.Class)] - public class DynamicFlowAttribute(bool scan = true) : Attribute - { - public bool Scan { get; set; } = scan; - } - - /// - /// 标记一个方法是什么类型,加载dll后用来拖拽到画布中 - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public class MethodDetailAttribute(DynamicNodeType methodDynamicType, - string methodTips = "", - bool scan = true, - string lockName = "") : Attribute - { - public bool Scan { get; set; } = scan; - public string MethodTips { get; } = methodTips; - public DynamicNodeType MethodDynamicType { get; } = methodDynamicType; - public string LockName { get; } = lockName; - } - - /// - /// 是否为显式参数 - /// - //[AttributeUsage(AttributeTargets.Parameter)] - //public class ExplicitAttribute : Attribute // where TEnum : Enum - //{ - //} - -} diff --git a/NodeFlow/Tool/DynamicTool.cs b/NodeFlow/Tool/DynamicTool.cs deleted file mode 100644 index 8645e6b..0000000 --- a/NodeFlow/Tool/DynamicTool.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Drawing.Printing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.NodeFlow.Tool -{ - - #region 锁、tsk工具 (已注释) - /*public class LockManager - { - private readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); - - public void CreateLock(string name) - { - _locks.TryAdd(name, new LockQueue()); - } - - public async Task AcquireLockAsync(string name, CancellationToken cancellationToken = default) - { - if (!_locks.ContainsKey(name)) - { - throw new ArgumentException($"Lock with name '{name}' does not exist."); - } - - var lockQueue = _locks[name]; - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - lock (lockQueue.Queue) - { - lockQueue.Queue.Enqueue(tcs); - if (lockQueue.Queue.Count == 1) - { - tcs.SetResult(true); - } - } - - await tcs.Task.ConfigureAwait(false); - - // 处理取消操作 - if (cancellationToken.CanBeCanceled) - { - cancellationToken.Register(() => - { - lock (lockQueue.Queue) - { - if (lockQueue.Queue.Contains(tcs)) - { - tcs.TrySetCanceled(); - } - } - }); - } - } - - public void ReleaseLock(string name) - { - if (!_locks.ContainsKey(name)) - { - throw new ArgumentException($"Lock with name '{name}' does not exist."); - } - - var lockQueue = _locks[name]; - - lock (lockQueue.Queue) - { - if (lockQueue.Queue.Count > 0) - { - lockQueue.Queue.Dequeue(); - - if (lockQueue.Queue.Count > 0) - { - var next = lockQueue.Queue.Peek(); - next.SetResult(true); - } - } - } - } - - private class LockQueue - { - public Queue> Queue { get; } = new Queue>(); - } - } - - - public interface ITaskResult - { - object Result { get; } - } - - public class TaskResult : ITaskResult - { - public TaskResult(T result) - { - Result = result; - } - - public T Result { get; } - - object ITaskResult.Result => Result; - } - - public class DynamicTasks - { - private static readonly ConcurrentDictionary> TaskGuidPairs = new(); - public static Task GetTask(string Guid) - { - TaskGuidPairs.TryGetValue(Guid, out Task task); - return task; - } - - public static bool AddTask(string Guid, T result) - { - var task = Task.FromResult(new TaskResult(result)); - - return TaskGuidPairs.TryAdd(Guid, task); - } - } - public class TaskNodeManager - { - private readonly ConcurrentDictionary _taskQueues = new ConcurrentDictionary(); - - public void CreateTaskNode(string name) - { - _taskQueues.TryAdd(name, new TaskQueue()); - } - - public async Task WaitForTaskNodeAsync(string name, CancellationToken cancellationToken = default) - { - if (!_taskQueues.ContainsKey(name)) - { - throw new ArgumentException($"Task node with name '{name}' does not exist."); - } - - var taskQueue = _taskQueues[name]; - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - lock (taskQueue.Queue) - { - taskQueue.Queue.Enqueue(tcs); - if (taskQueue.Queue.Count == 1) - { - tcs.SetResult(true); - } - } - - await tcs.Task.ConfigureAwait(false); - - // 处理取消操作 - if (cancellationToken.CanBeCanceled) - { - cancellationToken.Register(() => - { - lock (taskQueue.Queue) - { - if (taskQueue.Queue.Contains(tcs)) - { - tcs.TrySetCanceled(); - } - } - }); - } - } - - public void CompleteTaskNode(string name) - { - if (!_taskQueues.ContainsKey(name)) - { - throw new ArgumentException($"Task node with name '{name}' does not exist."); - } - - var taskQueue = _taskQueues[name]; - - lock (taskQueue.Queue) - { - if (taskQueue.Queue.Count > 0) - { - taskQueue.Queue.Dequeue(); - - if (taskQueue.Queue.Count > 0) - { - var next = taskQueue.Queue.Peek(); - next.SetResult(true); - } - } - } - } - - private class TaskQueue - { - public Queue> Queue { get; } = new Queue>(); - } - }*/ - #endregion - - - -} diff --git a/NodeFlow/Tool/NodeModelBaseFunc.cs b/NodeFlow/Tool/NodeModelBaseFunc.cs deleted file mode 100644 index 45eaf05..0000000 --- a/NodeFlow/Tool/NodeModelBaseFunc.cs +++ /dev/null @@ -1,460 +0,0 @@ -using Newtonsoft.Json; -using Serein.Library.Api; -using Serein.Library.Entity; -using Serein.Library.Enums; -using Serein.NodeFlow.Tool.SerinExpression; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Serein.Library.Base -{ - /// - /// 节点基类(数据):条件控件,动作控件,条件区域,动作区域 - /// - // public abstract partial class NodeModelBase : IDynamicFlowNode - public static class NodeFunc - { - /// - /// 执行节点对应的方法 - /// - /// 流程上下文 - /// 节点传回数据对象 - public static object? Execute(this NodeModelBase nodeModelBase, IDynamicContext context) - { - MethodDetails md = nodeModelBase.MethodDetails; - object? result = null; - var del = md.MethodDelegate; - try - { - if (md.ExplicitDatas.Length == 0) - { - if (md.ReturnType == typeof(void)) - { - ((Action)del).Invoke(md.ActingInstance); - } - else - { - result = ((Func)del).Invoke(md.ActingInstance); - } - } - else - { - object?[]? parameters = nodeModelBase.GetParameters(context, md); - if (md.ReturnType == typeof(void)) - { - ((Action)del).Invoke(md.ActingInstance, parameters); - } - else - { - result = ((Func)del).Invoke(md.ActingInstance, parameters); - } - } - - return result; - } - catch (Exception ex) - { - nodeModelBase.FlowState = FlowStateType.Error; - nodeModelBase.RuningException = ex; - } - - return result; - } - - /// - /// 执行等待触发器的方法 - /// - /// - /// 节点传回数据对象 - /// - public static async Task ExecuteAsync(this NodeModelBase nodeModel, IDynamicContext context) - { - MethodDetails md = nodeModel.MethodDetails; - object? result = null; - - IFlipflopContext flipflopContext = null; - try - { - // 调用委托并获取结果 - if (md.ExplicitDatas.Length == 0) - { - flipflopContext = await ((Func>)md.MethodDelegate).Invoke(md.ActingInstance); - } - else - { - object?[]? parameters = nodeModel.GetParameters(context, md); - flipflopContext = await ((Func>)md.MethodDelegate).Invoke(md.ActingInstance, parameters); - } - - if (flipflopContext != null) - { - nodeModel.FlowState = flipflopContext.State; - if (flipflopContext.State == FlowStateType.Succeed) - { - result = flipflopContext.Data; - } - else - { - result = null; - } - } - } - catch (Exception ex) - { - nodeModel.FlowState = FlowStateType.Error; - nodeModel.RuningException = ex; - } - - return result; - } - - /// - /// 开始执行 - /// - /// - /// - public static async Task StartExecution(this NodeModelBase nodeModel, IDynamicContext context) - { - var cts = context.SereinIoc.GetOrInstantiate(); - - Stack stack = []; - stack.Push(nodeModel); - var md = nodeModel.MethodDetails; - while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环 - { - // 从栈中弹出一个节点作为当前节点进行处理 - var currentNode = stack.Pop(); - - // 设置方法执行的对象 - if (currentNode.MethodDetails != null) - { - currentNode.MethodDetails.ActingInstance ??= context.SereinIoc.GetOrInstantiate(md.ActingInstanceType); - } - - // 获取上游分支,首先执行一次 - var upstreamNodes = currentNode.UpstreamBranch; - for (int i = upstreamNodes.Count - 1; i >= 0; i--) - { - upstreamNodes[i].PreviousNode = currentNode; - await upstreamNodes[i].StartExecution(context); - } - - if (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == NodeType.Flipflop) - { - // 触发器节点 - currentNode.FlowData = await currentNode.ExecuteAsync(context); - } - else - { - // 动作节点 - currentNode.FlowData = currentNode.Execute(context); - } - - var nextNodes = currentNode.FlowState switch - { - FlowStateType.Succeed => currentNode.SucceedBranch, - FlowStateType.Fail => currentNode.FailBranch, - FlowStateType.Error => currentNode.ErrorBranch, - _ => throw new Exception("非预期的枚举值") - }; - - // 将下一个节点集合中的所有节点逆序推入栈中 - for (int i = nextNodes.Count - 1; i >= 0; i--) - { - nextNodes[i].PreviousNode = currentNode; - stack.Push(nextNodes[i]); - } - } - } - - /// - /// 获取对应的参数数组 - /// - public static object[]? GetParameters(this NodeModelBase nodeModel, IDynamicContext context, MethodDetails md) - { - // 用正确的大小初始化参数数组 - var types = md.ExplicitDatas.Select(it => it.DataType).ToArray(); - if (types.Length == 0) - { - return [md.ActingInstance]; - } - - object[]? parameters = new object[types.Length]; - - for (int i = 0; i < types.Length; i++) - { - - var mdEd = md.ExplicitDatas[i]; - Type type = mdEd.DataType; - - var f1 = nodeModel.PreviousNode?.FlowData?.GetType(); - var f2 = mdEd.DataType; - if (type == typeof(IDynamicContext)) - { - parameters[i] = context; - } - else if (type == typeof(MethodDetails)) - { - parameters[i] = md; - } - else if (type == typeof(NodeModelBase)) - { - parameters[i] = nodeModel; - } - else if (mdEd.IsExplicitData) // 显式参数 - { - // 判断是否使用表达式解析 - if (mdEd.DataValue[0] == '@') - { - var expResult = SerinExpressionEvaluator.Evaluate(mdEd.DataValue, nodeModel.PreviousNode?.FlowData, out bool isChange); - - - if (mdEd.DataType.IsEnum) - { - var enumValue = Enum.Parse(mdEd.DataType, mdEd.DataValue); - parameters[i] = enumValue; - } - else if (mdEd.ExplicitType == typeof(string)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(string)); - } - else if (mdEd.ExplicitType == typeof(bool)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(bool)); - } - else if (mdEd.ExplicitType == typeof(int)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(int)); - } - else if (mdEd.ExplicitType == typeof(double)) - { - parameters[i] = Convert.ChangeType(expResult, typeof(double)); - } - else - { - parameters[i] = expResult; - //parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType); - } - } - else - { - if (mdEd.DataType.IsEnum) - { - var enumValue = Enum.Parse(mdEd.DataType, mdEd.DataValue); - parameters[i] = enumValue; - } - else if (mdEd.ExplicitType == typeof(string)) - { - parameters[i] = mdEd.DataValue; - } - else if (mdEd.ExplicitType == typeof(bool)) - { - parameters[i] = bool.Parse(mdEd.DataValue); - } - else if (mdEd.ExplicitType == typeof(int)) - { - parameters[i] = int.Parse(mdEd.DataValue); - } - else if (mdEd.ExplicitType == typeof(double)) - { - parameters[i] = double.Parse(mdEd.DataValue); - } - else - { - parameters[i] = ""; - - //parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType); - } - } - - - } - else if (f1 != null && f2 != null) - { - if (f2.IsAssignableFrom(f1) || f2.FullName.Equals(f1.FullName)) - { - parameters[i] = nodeModel.PreviousNode?.FlowData; - - } - } - else - { - - - var tmpParameter = nodeModel.PreviousNode?.FlowData?.ToString(); - if (mdEd.DataType.IsEnum) - { - - var enumValue = Enum.Parse(mdEd.DataType, tmpParameter); - - parameters[i] = enumValue; - } - else if (mdEd.DataType == typeof(string)) - { - - parameters[i] = tmpParameter; - - } - else if (mdEd.DataType == typeof(bool)) - { - - parameters[i] = bool.Parse(tmpParameter); - - } - else if (mdEd.DataType == typeof(int)) - { - - parameters[i] = int.Parse(tmpParameter); - - } - else if (mdEd.DataType == typeof(double)) - { - - parameters[i] = double.Parse(tmpParameter); - - } - else - { - if (tmpParameter != null && mdEd.DataType != null) - { - - parameters[i] = ConvertValue(tmpParameter, mdEd.DataType); - - } - } - } - - } - return parameters; - } - - /// - /// json文本反序列化为对象 - /// - /// - /// - /// - private static dynamic? ConvertValue(string value, Type targetType) - { - try - { - if (!string.IsNullOrEmpty(value)) - { - return JsonConvert.DeserializeObject(value, targetType); - } - else - { - return null; - } - } - catch (JsonReaderException ex) - { - Console.WriteLine(ex); - return value; - } - catch (JsonSerializationException ex) - { - // 如果无法转为对应的JSON对象 - int startIndex = ex.Message.IndexOf("to type '") + "to type '".Length; // 查找类型信息开始的索引 - int endIndex = ex.Message.IndexOf('\''); // 查找类型信息结束的索引 - var typeInfo = ex.Message[startIndex..endIndex]; // 提取出错类型信息,该怎么传出去? - Console.WriteLine("无法转为对应的JSON对象:" + typeInfo); - return null; - } - catch // (Exception ex) - { - return value; - } - } - - - - - - #region 完整的ExecuteAsync调用方法(不要删除) - //public virtual async Task ExecuteAsync(DynamicContext context) - //{ - // MethodDetails md = MethodDetails; - // object? result = null; - // if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) - // { - // if (md.ExplicitDatas.Length == 0) - // { - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance); - // } - // else if (md.ReturnType == typeof(Task)) - // { - // // 调用委托并获取结果 - // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance); - - // if (flipflopContext != null) - // { - // if (flipflopContext.State == FfState.Cancel) - // { - // throw new Exception("this async task is cancel."); - // } - // else - // { - // if (flipflopContext.State == FfState.Succeed) - // { - // CurrentState = true; - // result = flipflopContext.Data; - // } - // else - // { - // CurrentState = false; - // } - // } - // } - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance); - // } - // } - // else - // { - // object?[]? parameters = GetParameters(context, MethodDetails); - // if (md.ReturnType == typeof(void)) - // { - // ((Action)del).Invoke(md.ActingInstance, parameters); - // } - // else if (md.ReturnType == typeof(Task)) - // { - // // 调用委托并获取结果 - // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance, parameters); - - // if (flipflopContext != null) - // { - // if (flipflopContext.State == FfState.Cancel) - // { - // throw new Exception("取消此异步"); - // } - // else - // { - // CurrentState = flipflopContext.State == FfState.Succeed; - // result = flipflopContext.Data; - // } - // } - // } - // else - // { - // result = ((Func)del).Invoke(md.ActingInstance, parameters); - // } - // } - // context.SetFlowData(result); - // } - // return result; - //} - #endregion - - - - - } -} diff --git a/NodeFlow/Tool/SereinExpression/Resolver/BoolConditionResolver.cs b/NodeFlow/Tool/SereinExpression/Resolver/BoolConditionResolver.cs new file mode 100644 index 0000000..f5fe3ed --- /dev/null +++ b/NodeFlow/Tool/SereinExpression/Resolver/BoolConditionResolver.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Tool.SereinExpression.Resolver +{ + public class BoolConditionResolver : SereinConditionResolver + { + public enum Operator + { + /// + /// 是 + /// + Is + } + + public Operator Op { get; set; } + public bool Value { get; set; } + + public override bool Evaluate(object obj) + { + + if (obj is bool boolObj) + { + return boolObj == Value; + /*switch (Op) + { + case Operator.Is: + return boolObj == Value; + }*/ + } + return false; + } + } + +} diff --git a/NodeFlow/Tool/SereinExpression/Resolver/MemberConditionResolver.cs b/NodeFlow/Tool/SereinExpression/Resolver/MemberConditionResolver.cs new file mode 100644 index 0000000..9d15635 --- /dev/null +++ b/NodeFlow/Tool/SereinExpression/Resolver/MemberConditionResolver.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Tool.SereinExpression.Resolver +{ + public class MemberConditionResolver : SereinConditionResolver where T : struct, IComparable + { + //public string MemberPath { get; set; } + public ValueTypeConditionResolver.Operator Op { get; set; } + public object? TargetObj { get; set; } + public T Value { get; set; } + + public string ArithmeticExpression { get; set; } + + public override bool Evaluate(object? obj) + { + //object? memberValue = GetMemberValue(obj, MemberPath); + if (TargetObj is T typedObj) + { + return new ValueTypeConditionResolver + { + Op = Op, + Value = Value, + ArithmeticExpression = ArithmeticExpression, + }.Evaluate(typedObj); + } + return false; + } + + //private object? GetMemberValue(object? obj, string memberPath) + //{ + // string[] members = memberPath[1..].Split('.'); + // foreach (var member in members) + // { + // if (obj == null) return null; + // Type type = obj.GetType(); + // PropertyInfo? propertyInfo = type.GetProperty(member); + // FieldInfo? fieldInfo = type.GetField(member); + // if (propertyInfo != null) + // obj = propertyInfo.GetValue(obj); + // else if (fieldInfo != null) + // obj = fieldInfo.GetValue(obj); + // else + // throw new ArgumentException($"Member {member} not found in type {type.FullName}"); + // } + // return obj; + //} + } + +} diff --git a/NodeFlow/Tool/SereinExpression/Resolver/MemberStringConditionResolver.cs b/NodeFlow/Tool/SereinExpression/Resolver/MemberStringConditionResolver.cs new file mode 100644 index 0000000..e75346d --- /dev/null +++ b/NodeFlow/Tool/SereinExpression/Resolver/MemberStringConditionResolver.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Tool.SereinExpression.Resolver +{ + public class MemberStringConditionResolver : SereinConditionResolver + { + public string MemberPath { get; set; } + + public StringConditionResolver.Operator Op { get; set; } + + public string Value { get; set; } + + + public override bool Evaluate(object obj) + { + object memberValue = GetMemberValue(obj, MemberPath); + if (memberValue is string strObj) + { + return new StringConditionResolver + { + Op = Op, + Value = Value + }.Evaluate(strObj); + } + return false; + } + + private object GetMemberValue(object? obj, string memberPath) + { + string[] members = memberPath[1..].Split('.'); + foreach (var member in members) + { + + if (obj == null) return null; + + Type type = obj.GetType(); + PropertyInfo? propertyInfo = type.GetProperty(member); + FieldInfo? fieldInfo = type.GetField(member); + if (propertyInfo != null) + obj = propertyInfo.GetValue(obj); + else if (fieldInfo != null) + obj = fieldInfo.GetValue(obj); + else + throw new ArgumentException($"Member {member} not found in type {type.FullName}"); + } + + return obj; + + } + + + private static string GetArithmeticExpression(string part) + { + int startIndex = part.IndexOf('['); + int endIndex = part.IndexOf(']'); + if (startIndex >= 0 && endIndex > startIndex) + { + return part.Substring(startIndex + 1, endIndex - startIndex - 1); + } + + return null; + + } + + + + + + } + +} diff --git a/NodeFlow/Tool/SereinExpression/Resolver/PassConditionResolver.cs b/NodeFlow/Tool/SereinExpression/Resolver/PassConditionResolver.cs new file mode 100644 index 0000000..5a30e7e --- /dev/null +++ b/NodeFlow/Tool/SereinExpression/Resolver/PassConditionResolver.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Tool.SereinExpression.Resolver +{ + public class PassConditionResolver : SereinConditionResolver + { + public Operator Op { get; set; } + public override bool Evaluate(object obj) + { + /*return Op switch + { + Operator.Pass => true, + Operator.NotPass => false, + _ => throw new NotSupportedException("不支持的条件类型") + };*/ + switch (Op) + { + case Operator.Pass: + return true; + case Operator.NotPass: + return false; + default: + throw new NotSupportedException("不支持的条件类型"); + + } + } + + public enum Operator + { + Pass, + NotPass, + } + } +} diff --git a/NodeFlow/Tool/SereinExpression/Resolver/StringConditionResolver.cs b/NodeFlow/Tool/SereinExpression/Resolver/StringConditionResolver.cs new file mode 100644 index 0000000..7e2d178 --- /dev/null +++ b/NodeFlow/Tool/SereinExpression/Resolver/StringConditionResolver.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Tool.SereinExpression.Resolver +{ + public class StringConditionResolver : SereinConditionResolver + { + public enum Operator + { + /// + /// 出现过 + /// + Contains, + /// + /// 没有出现过 + /// + DoesNotContain, + /// + /// 相等 + /// + Equal, + /// + /// 不相等 + /// + NotEqual, + /// + /// 起始字符串等于 + /// + StartsWith, + /// + /// 结束字符串等于 + /// + EndsWith + } + + public Operator Op { get; set; } + + public string Value { get; set; } + + + public override bool Evaluate(object obj) + { + if (obj is string strObj) + { + /*return Op switch + { + Operator.Contains => strObj.Contains(Value), + Operator.DoesNotContain => !strObj.Contains(Value), + Operator.Equal => strObj == Value, + Operator.NotEqual => strObj != Value, + Operator.StartsWith => strObj.StartsWith(Value), + Operator.EndsWith => strObj.EndsWith(Value), + _ => throw new NotSupportedException("不支持的条件类型"), + };*/ + + switch (Op) + { + case Operator.Contains: + return strObj.Contains(Value); + case Operator.DoesNotContain: + return !strObj.Contains(Value); + case Operator.Equal: + return strObj == Value; + case Operator.NotEqual: + return strObj != Value; + case Operator.StartsWith: + return strObj.StartsWith(Value); + case Operator.EndsWith: + return strObj.EndsWith(Value); + default: + throw new NotSupportedException("不支持的条件类型"); + } + } + return false; + } + } +} diff --git a/NodeFlow/Tool/SereinExpression/Resolver/ValueTypeConditionResolver.cs b/NodeFlow/Tool/SereinExpression/Resolver/ValueTypeConditionResolver.cs new file mode 100644 index 0000000..f5c9c97 --- /dev/null +++ b/NodeFlow/Tool/SereinExpression/Resolver/ValueTypeConditionResolver.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Tool.SereinExpression.Resolver +{ + public class ValueTypeConditionResolver : SereinConditionResolver where T : struct, IComparable + { + public enum Operator + { + /// + /// 不进行任何操作 + /// + Node, + /// + /// 大于 + /// + GreaterThan, + /// + /// 小于 + /// + LessThan, + /// + /// 等于 + /// + Equal, + /// + /// 大于或等于 + /// + GreaterThanOrEqual, + /// + /// 小于或等于 + /// + LessThanOrEqual, + /// + /// 在两者之间 + /// + InRange, + /// + /// 不在两者之间 + /// + OutOfRange + } + + public Operator Op { get; set; } + public T Value { get; set; } + public T RangeStart { get; set; } + public T RangeEnd { get; set; } + + public string ArithmeticExpression { get; set; } + + + public override bool Evaluate(object obj) + { + if (obj is T typedObj) + { + double numericValue = Convert.ToDouble(typedObj); + if (!string.IsNullOrEmpty(ArithmeticExpression)) + { + numericValue = SerinArithmeticExpressionEvaluator.Evaluate(ArithmeticExpression, numericValue); + } + + T evaluatedValue = (T)Convert.ChangeType(numericValue, typeof(T)); + + /*return Op switch + { + Operator.GreaterThan => evaluatedValue.CompareTo(Value) > 0, + Operator.LessThan => evaluatedValue.CompareTo(Value) < 0, + Operator.Equal => evaluatedValue.CompareTo(Value) == 0, + Operator.GreaterThanOrEqual => evaluatedValue.CompareTo(Value) >= 0, + Operator.LessThanOrEqual => evaluatedValue.CompareTo(Value) <= 0, + Operator.InRange => evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0, + Operator.OutOfRange => evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0, + _ => throw new NotSupportedException("不支持的条件类型") + };*/ + switch (Op) + { + case Operator.GreaterThan: + return evaluatedValue.CompareTo(Value) > 0; + case Operator.LessThan: + return evaluatedValue.CompareTo(Value) < 0; + case Operator.Equal: + return evaluatedValue.CompareTo(Value) == 0; + case Operator.GreaterThanOrEqual: + return evaluatedValue.CompareTo(Value) >= 0; + case Operator.LessThanOrEqual: + return evaluatedValue.CompareTo(Value) <= 0; + case Operator.InRange: + return evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0; + case Operator.OutOfRange: + return evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0; + } + } + return false; + } + } + +} diff --git a/Library/Utils/SerinExpression/SerinConditionParser.cs b/NodeFlow/Tool/SereinExpression/SereinConditionParser.cs similarity index 81% rename from Library/Utils/SerinExpression/SerinConditionParser.cs rename to NodeFlow/Tool/SereinExpression/SereinConditionParser.cs index 7f3e92f..0072fc5 100644 --- a/Library/Utils/SerinExpression/SerinConditionParser.cs +++ b/NodeFlow/Tool/SereinExpression/SereinConditionParser.cs @@ -1,11 +1,11 @@ -using System; +using Serein.NodeFlow.Tool.SereinExpression.Resolver; using System.Globalization; using System.Reflection; -namespace Serein.NodeFlow.Tool.SerinExpression +namespace Serein.NodeFlow.Tool.SereinExpression { - public class SerinConditionParser + public class SereinConditionParser { public static bool To(T data, string expression) { @@ -22,7 +22,7 @@ namespace Serein.NodeFlow.Tool.SerinExpression } } - public static ConditionResolver ConditionParse(object data, string expression) + public static SereinConditionResolver ConditionParse(object data, string expression) { if (expression.StartsWith('.')) // 表达式前缀属于从上一个节点数据对象获取成员值 { @@ -79,51 +79,57 @@ namespace Serein.NodeFlow.Tool.SerinExpression } return obj; } + + /// /// 解析对象表达式 /// - private static ConditionResolver ParseObjectExpression(object data, string expression) + private static SereinConditionResolver ParseObjectExpression(object data, string expression) { var parts = expression.Split(' '); - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - int typeStartIndex = expression.IndexOf('<'); - int typeEndIndex = expression.IndexOf('>'); - + string operatorStr = parts[0]; // 获取操作类型 + string valueStr; //= string.Join(' ', parts, 1, parts.Length - 1); string memberPath; Type type; object? targetObj; + + // 尝试获取指定类型 + int typeStartIndex = expression.IndexOf('<'); + int typeEndIndex = expression.IndexOf('>'); if (typeStartIndex + typeStartIndex == -2) { + // 如果不需要转为指定类型 memberPath = operatorStr; targetObj = GetMemberValue(data, operatorStr); - type = targetObj.GetType(); - - operatorStr = parts[1].ToLower(); + operatorStr = parts[1].ToLower(); // valueStr = string.Join(' ', parts.Skip(2)); } else { + // 类型语法不正确 if (typeStartIndex >= typeEndIndex) { throw new ArgumentException("无效的表达式格式"); } memberPath = expression.Substring(0, typeStartIndex).Trim(); - string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1).Trim().ToLower(); + string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1) + .Trim().ToLower(); // 手动置顶的类型 + + // 对象取值表达式 parts = expression.Substring(typeEndIndex + 1).Trim().Split(' '); if (parts.Length == 3) { - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); + operatorStr = parts[1].ToLower(); // 操作类型 + valueStr = string.Join(' ', parts.Skip(2)); // 表达式值 } else { - operatorStr = parts[0].ToLower(); - valueStr = string.Join(' ', parts.Skip(1)); + operatorStr = parts[0].ToLower(); // 操作类型 + valueStr = string.Join(' ', parts.Skip(1)); // 表达式值 } - targetObj = GetMemberValue(data, memberPath); + + targetObj = GetMemberValue(data, memberPath);// 获取对象成员,作为表达式的目标对象 Type? tempType = typeStr switch { @@ -136,8 +142,7 @@ namespace Serein.NodeFlow.Tool.SerinExpression type = tempType ?? throw new ArgumentException("对象表达式无效的类型声明"); } - - + #region 解析类型 int if (type == typeof(int)) { int value = int.Parse(valueStr, CultureInfo.InvariantCulture); @@ -150,6 +155,8 @@ namespace Serein.NodeFlow.Tool.SerinExpression ArithmeticExpression = GetArithmeticExpression(parts[0]) }; } + #endregion + #region 解析类型 double else if (type == typeof(double)) { double value = double.Parse(valueStr, CultureInfo.InvariantCulture); @@ -163,6 +170,8 @@ namespace Serein.NodeFlow.Tool.SerinExpression }; } + #endregion + #region 解析类型 bool else if (type == typeof(bool)) { return new MemberConditionResolver @@ -172,6 +181,8 @@ namespace Serein.NodeFlow.Tool.SerinExpression Op = (ValueTypeConditionResolver.Operator)ParseBoolOperator(operatorStr) }; } + #endregion + #region 解析类型 string else if (type == typeof(string)) { return new MemberStringConditionResolver @@ -180,12 +191,22 @@ namespace Serein.NodeFlow.Tool.SerinExpression Op = ParseStringOperator(operatorStr), Value = valueStr }; - } + } + #endregion throw new NotSupportedException($"Type {type} is not supported."); } - private static ConditionResolver ParseSimpleExpression(object data, string expression) + + /// + /// 条件表达式解析 + /// + /// + /// + /// + /// + /// + private static SereinConditionResolver ParseSimpleExpression(object data, string expression) { if ("pass".Equals(expression.ToLower())) { @@ -252,7 +273,6 @@ namespace Serein.NodeFlow.Tool.SerinExpression }; } - } else if (type == typeof(double)) { @@ -286,6 +306,14 @@ namespace Serein.NodeFlow.Tool.SerinExpression } + + /// + /// 数值操作类型 + /// + /// + /// + /// + /// private static ValueTypeConditionResolver.Operator ParseValueTypeOperator(string operatorStr) where T : struct, IComparable { return operatorStr switch @@ -305,6 +333,12 @@ namespace Serein.NodeFlow.Tool.SerinExpression }; } + /// + /// 布尔操作类型 + /// + /// + /// + /// private static BoolConditionResolver.Operator ParseBoolOperator(string operatorStr) { return operatorStr switch @@ -317,6 +351,12 @@ namespace Serein.NodeFlow.Tool.SerinExpression }; } + /// + /// 字符串操作类型 + /// + /// + /// + /// private static StringConditionResolver.Operator ParseStringOperator(string operatorStr) { return operatorStr switch @@ -337,6 +377,6 @@ namespace Serein.NodeFlow.Tool.SerinExpression _ => throw new ArgumentException($"Invalid operator {operatorStr} for string type.") }; } - } + } } diff --git a/NodeFlow/Tool/SereinExpression/SereinConditionResolver.cs b/NodeFlow/Tool/SereinExpression/SereinConditionResolver.cs new file mode 100644 index 0000000..e0ac6be --- /dev/null +++ b/NodeFlow/Tool/SereinExpression/SereinConditionResolver.cs @@ -0,0 +1,12 @@ +using System.Reflection; + +namespace Serein.NodeFlow.Tool.SereinExpression +{ + /// + /// 条件解析抽象类 + /// + public abstract class SereinConditionResolver + { + public abstract bool Evaluate(object obj); + } +} diff --git a/Library.Core/SerinExpression/SerinExpressionEvaluator.cs b/NodeFlow/Tool/SereinExpression/SerinExpressionEvaluator.cs similarity index 82% rename from Library.Core/SerinExpression/SerinExpressionEvaluator.cs rename to NodeFlow/Tool/SereinExpression/SerinExpressionEvaluator.cs index 0a12633..7d391b4 100644 --- a/Library.Core/SerinExpression/SerinExpressionEvaluator.cs +++ b/NodeFlow/Tool/SereinExpression/SerinExpressionEvaluator.cs @@ -1,7 +1,14 @@ using System.Data; -namespace Serein.LibraryCore.SerinExpression +namespace Serein.NodeFlow.Tool.SereinExpression { + /// + /// 使用表达式操作/获取 对象的值 + /// 获取值 @get .xx.xxx + /// 设置值 @set .xx.xxx = [data] + /// + /// 操作的对象 + /// public class SerinArithmeticExpressionEvaluator { private static readonly DataTable table = new DataTable(); @@ -30,7 +37,7 @@ namespace Serein.LibraryCore.SerinExpression /// /// 表达式 /// 操作对象 - /// 是否改变了对象(get语法) + /// 是否改变了对象(Set语法) /// /// /// @@ -56,11 +63,11 @@ namespace Serein.LibraryCore.SerinExpression isChange = operation switch { - "@num" => true, + /*"@num" => true, "@call" => true, - "@get" => true, + "@get" => true,*/ "@set" => false, - _ => throw new NotSupportedException($"Operation {operation} is not supported.") + _ => true, }; return result; @@ -70,6 +77,13 @@ namespace Serein.LibraryCore.SerinExpression private static readonly char[] separator = ['(', ')']; private static readonly char[] separatorArray = [',']; + /// + /// 调用目标方法 + /// + /// 目标实例 + /// 方法名称 + /// + /// private static object InvokeMethod(object target, string methodCall) { var methodParts = methodCall.Split(separator, StringSplitOptions.RemoveEmptyEntries); @@ -98,7 +112,13 @@ namespace Serein.LibraryCore.SerinExpression return method.Invoke(target, parameterValues); } - + /// + /// 获取值 + /// + /// 目标实例 + /// 属性路径 + /// + /// private static object GetMember(object target, string memberPath) { var members = memberPath.Split('.'); @@ -135,7 +155,13 @@ namespace Serein.LibraryCore.SerinExpression return target; } - + /// + /// 设置目标的值 + /// + /// 目标实例 + /// 属性路径 + /// + /// private static object SetMember(object target, string assignment) { var parts = assignment.Split(new[] { '=' }, 2); @@ -202,6 +228,12 @@ namespace Serein.LibraryCore.SerinExpression return target; } + /// + /// 计算数学简单表达式 + /// + /// + /// + /// private static double ComputedNumber(object value, string expression) { double numericValue = Convert.ToDouble(value); diff --git a/NodeFlow/Tool/SerinExpression/ConditionResolver.cs b/NodeFlow/Tool/SerinExpression/ConditionResolver.cs deleted file mode 100644 index d46cba4..0000000 --- a/NodeFlow/Tool/SerinExpression/ConditionResolver.cs +++ /dev/null @@ -1,337 +0,0 @@ -using System.Reflection; - -namespace Serein.NodeFlow.Tool.SerinExpression -{ - /// - /// 条件解析抽象类 - /// - public abstract class ConditionResolver - { - public abstract bool Evaluate(object obj); - } - - public class PassConditionResolver : ConditionResolver - { - public Operator Op { get; set; } - public override bool Evaluate(object obj) - { - return Op switch - { - Operator.Pass => true, - Operator.NotPass => false, - _ => throw new NotSupportedException("不支持的条件类型") - }; - } - - public enum Operator - { - Pass, - NotPass, - } - - } - - public class ValueTypeConditionResolver : ConditionResolver where T : struct, IComparable - { - public enum Operator - { - /// - /// 不进行任何操作 - /// - Node, - /// - /// 大于 - /// - GreaterThan, - /// - /// 小于 - /// - LessThan, - /// - /// 等于 - /// - Equal, - /// - /// 大于或等于 - /// - GreaterThanOrEqual, - /// - /// 小于或等于 - /// - LessThanOrEqual, - /// - /// 在两者之间 - /// - InRange, - /// - /// 不在两者之间 - /// - OutOfRange - } - - public Operator Op { get; set; } - public T Value { get; set; } - public T RangeStart { get; set; } - public T RangeEnd { get; set; } - - public string ArithmeticExpression { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is T typedObj) - { - double numericValue = Convert.ToDouble(typedObj); - if (!string.IsNullOrEmpty(ArithmeticExpression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(ArithmeticExpression, numericValue); - } - - T evaluatedValue = (T)Convert.ChangeType(numericValue, typeof(T)); - - return Op switch - { - Operator.GreaterThan => evaluatedValue.CompareTo(Value) > 0, - Operator.LessThan => evaluatedValue.CompareTo(Value) < 0, - Operator.Equal => evaluatedValue.CompareTo(Value) == 0, - Operator.GreaterThanOrEqual => evaluatedValue.CompareTo(Value) >= 0, - Operator.LessThanOrEqual => evaluatedValue.CompareTo(Value) <= 0, - Operator.InRange => evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0, - Operator.OutOfRange => evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0, - _ => throw new NotSupportedException("不支持的条件类型") - }; - /* switch (Op) - { - case Operator.GreaterThan: - return evaluatedValue.CompareTo(Value) > 0; - case Operator.LessThan: - return evaluatedValue.CompareTo(Value) < 0; - case Operator.Equal: - return evaluatedValue.CompareTo(Value) == 0; - case Operator.GreaterThanOrEqual: - return evaluatedValue.CompareTo(Value) >= 0; - case Operator.LessThanOrEqual: - return evaluatedValue.CompareTo(Value) <= 0; - case Operator.InRange: - return evaluatedValue.CompareTo(RangeStart) >= 0 && evaluatedValue.CompareTo(RangeEnd) <= 0; - case Operator.OutOfRange: - return evaluatedValue.CompareTo(RangeStart) < 0 || evaluatedValue.CompareTo(RangeEnd) > 0; - }*/ - } - return false; - } - } - - public class BoolConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 是 - /// - Is - } - - public Operator Op { get; set; } - public bool Value { get; set; } - - public override bool Evaluate(object obj) - { - - if (obj is bool boolObj) - { - return boolObj == Value; - /*switch (Op) - { - case Operator.Is: - return boolObj == Value; - }*/ - } - return false; - } - } - - public class StringConditionResolver : ConditionResolver - { - public enum Operator - { - /// - /// 出现过 - /// - Contains, - /// - /// 没有出现过 - /// - DoesNotContain, - /// - /// 相等 - /// - Equal, - /// - /// 不相等 - /// - NotEqual, - /// - /// 起始字符串等于 - /// - StartsWith, - /// - /// 结束字符串等于 - /// - EndsWith - } - - public Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - if (obj is string strObj) - { - return Op switch - { - Operator.Contains => strObj.Contains(Value), - Operator.DoesNotContain => !strObj.Contains(Value), - Operator.Equal => strObj == Value, - Operator.NotEqual => strObj != Value, - Operator.StartsWith => strObj.StartsWith(Value), - Operator.EndsWith => strObj.EndsWith(Value), - _ => throw new NotSupportedException("不支持的条件类型"), - }; - - /* switch (Op) - { - case Operator.Contains: - return strObj.Contains(Value); - case Operator.DoesNotContain: - return !strObj.Contains(Value); - case Operator.Equal: - return strObj == Value; - case Operator.NotEqual: - return strObj != Value; - case Operator.StartsWith: - return strObj.StartsWith(Value); - case Operator.EndsWith: - return strObj.EndsWith(Value); - }*/ - } - return false; - } - } - public class MemberConditionResolver : ConditionResolver where T : struct, IComparable - { - //public string MemberPath { get; set; } - public ValueTypeConditionResolver.Operator Op { get; set; } - public object? TargetObj { get; set; } - public T Value { get; set; } - - public string ArithmeticExpression { get; set; } - - public override bool Evaluate(object? obj) - { - //object? memberValue = GetMemberValue(obj, MemberPath); - if (TargetObj is T typedObj) - { - return new ValueTypeConditionResolver - { - Op = Op, - Value = Value, - ArithmeticExpression = ArithmeticExpression, - }.Evaluate(typedObj); - } - return false; - } - - //private object? GetMemberValue(object? obj, string memberPath) - //{ - // string[] members = memberPath[1..].Split('.'); - // foreach (var member in members) - // { - // if (obj == null) return null; - // Type type = obj.GetType(); - // PropertyInfo? propertyInfo = type.GetProperty(member); - // FieldInfo? fieldInfo = type.GetField(member); - // if (propertyInfo != null) - // obj = propertyInfo.GetValue(obj); - // else if (fieldInfo != null) - // obj = fieldInfo.GetValue(obj); - // else - // throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - // } - // return obj; - //} - } - - public class MemberStringConditionResolver : ConditionResolver - { - - public string MemberPath { get; set; } - - public StringConditionResolver.Operator Op { get; set; } - - public string Value { get; set; } - - - public override bool Evaluate(object obj) - { - object memberValue = GetMemberValue(obj, MemberPath); - if (memberValue is string strObj) - { - return new StringConditionResolver - { - Op = Op, - Value = Value - }.Evaluate(strObj); - } - return false; - } - - private object GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - - if (obj == null) return null; - - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - - return obj; - - } - - - - - - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - - - - - - } - -} diff --git a/NodeFlow/Tool/SerinExpression/SerinConditionParser.cs b/NodeFlow/Tool/SerinExpression/SerinConditionParser.cs deleted file mode 100644 index 5d4a3bc..0000000 --- a/NodeFlow/Tool/SerinExpression/SerinConditionParser.cs +++ /dev/null @@ -1,341 +0,0 @@ -using System.Globalization; -using System.Reflection; - -namespace Serein.NodeFlow.Tool.SerinExpression -{ - - public class SerinConditionParser - { - public static bool To(T data, string expression) - { - try - { - - return ConditionParse(data, expression).Evaluate(data); - - } - catch (Exception ex) - { - Console.WriteLine(ex); - throw; - } - } - - public static ConditionResolver ConditionParse(object data, string expression) - { - if (expression.StartsWith('.')) // 表达式前缀属于从上一个节点数据对象获取成员值 - { - return ParseObjectExpression(data, expression); - } - else - { - return ParseSimpleExpression(data, expression); - } - - - //bool ContainsArithmeticOperators(string expression) - //{ - // return expression.Contains('+') || expression.Contains('-') || expression.Contains('*') || expression.Contains('/'); - //} - - } - - /// - /// 获取计算表达式的部分 - /// - /// - /// - private static string GetArithmeticExpression(string part) - { - int startIndex = part.IndexOf('['); - int endIndex = part.IndexOf(']'); - if (startIndex >= 0 && endIndex > startIndex) - { - return part.Substring(startIndex + 1, endIndex - startIndex - 1); - } - - return null; - - } - /// - /// 获取对象指定名称的成员 - /// - private static object? GetMemberValue(object? obj, string memberPath) - { - string[] members = memberPath[1..].Split('.'); - foreach (var member in members) - { - if (obj == null) return null; - Type type = obj.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(member); - FieldInfo? fieldInfo = type.GetField(member); - if (propertyInfo != null) - obj = propertyInfo.GetValue(obj); - else if (fieldInfo != null) - obj = fieldInfo.GetValue(obj); - else - throw new ArgumentException($"Member {member} not found in type {type.FullName}"); - } - return obj; - } - /// - /// 解析对象表达式 - /// - private static ConditionResolver ParseObjectExpression(object data, string expression) - { - var parts = expression.Split(' '); - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - int typeStartIndex = expression.IndexOf('<'); - int typeEndIndex = expression.IndexOf('>'); - - string memberPath; - Type type; - object? targetObj; - if (typeStartIndex + typeStartIndex == -2) - { - memberPath = operatorStr; - targetObj = GetMemberValue(data, operatorStr); - - type = targetObj.GetType(); - - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - if (typeStartIndex >= typeEndIndex) - { - throw new ArgumentException("无效的表达式格式"); - } - memberPath = expression.Substring(0, typeStartIndex).Trim(); - string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1).Trim().ToLower(); - parts = expression.Substring(typeEndIndex + 1).Trim().Split(' '); - if (parts.Length == 3) - { - operatorStr = parts[1].ToLower(); - valueStr = string.Join(' ', parts.Skip(2)); - } - else - { - operatorStr = parts[0].ToLower(); - valueStr = string.Join(' ', parts.Skip(1)); - } - targetObj = GetMemberValue(data, memberPath); - - Type? tempType = typeStr switch - { - "int" => typeof(int), - "double" => typeof(double), - "bool" => typeof(bool), - "string" => typeof(string), - _ => Type.GetType(typeStr) - }; - type = tempType ?? throw new ArgumentException("对象表达式无效的类型声明"); - } - - - - if (type == typeof(int)) - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - TargetObj = targetObj, - //MemberPath = memberPath, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - else if (type == typeof(bool)) - { - return new MemberConditionResolver - { - //MemberPath = memberPath, - TargetObj = targetObj, - Op = (ValueTypeConditionResolver.Operator)ParseBoolOperator(operatorStr) - }; - } - else if (type == typeof(string)) - { - return new MemberStringConditionResolver - { - MemberPath = memberPath, - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - private static ConditionResolver ParseSimpleExpression(object data, string expression) - { - if ("pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.Pass, - }; - } - else - { - if ("not pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - if ("!pass".Equals(expression.ToLower())) - { - return new PassConditionResolver - { - Op = PassConditionResolver.Operator.NotPass, - }; - } - } - - - var parts = expression.Split(' '); - - if (parts.Length < 2) - throw new ArgumentException("无效的表达式格式。"); - - //string typeStr = parts[0]; - string operatorStr = parts[0]; - string valueStr = string.Join(' ', parts, 1, parts.Length - 1); - - Type type = data.GetType();//Type.GetType(typeStr); - if (type == typeof(int)) - { - var op = ParseValueTypeOperator(operatorStr); - if (op == ValueTypeConditionResolver.Operator.InRange || op == ValueTypeConditionResolver.Operator.OutOfRange) - { - var temp = valueStr.Split('-'); - if (temp.Length < 2) - throw new ArgumentException($"范围无效:{valueStr}。"); - int rangeStart = int.Parse(temp[0], CultureInfo.InvariantCulture); - int rangeEnd = int.Parse(temp[1], CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - RangeStart = rangeStart, - RangeEnd = rangeEnd, - ArithmeticExpression = GetArithmeticExpression(parts[0]), - }; - } - else - { - int value = int.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = op, - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - - } - - } - else if (type == typeof(double)) - { - double value = double.Parse(valueStr, CultureInfo.InvariantCulture); - return new ValueTypeConditionResolver - { - Op = ParseValueTypeOperator(operatorStr), - Value = value, - ArithmeticExpression = GetArithmeticExpression(parts[0]) - }; - } - else if (type == typeof(bool)) - { - bool value = bool.Parse(valueStr); - return new BoolConditionResolver - { - Op = ParseBoolOperator(operatorStr), - Value = value, - }; - } - else if (type == typeof(string)) - { - return new StringConditionResolver - { - Op = ParseStringOperator(operatorStr), - Value = valueStr - }; - } - - throw new NotSupportedException($"Type {type} is not supported."); - } - - - private static ValueTypeConditionResolver.Operator ParseValueTypeOperator(string operatorStr) where T : struct, IComparable - { - return operatorStr switch - { - ">" => ValueTypeConditionResolver.Operator.GreaterThan, - "<" => ValueTypeConditionResolver.Operator.LessThan, - "=" => ValueTypeConditionResolver.Operator.Equal, - "==" => ValueTypeConditionResolver.Operator.Equal, - ">=" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "≥" => ValueTypeConditionResolver.Operator.GreaterThanOrEqual, - "<=" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "≤" => ValueTypeConditionResolver.Operator.LessThanOrEqual, - "equals" => ValueTypeConditionResolver.Operator.Equal, - "in" => ValueTypeConditionResolver.Operator.InRange, - "!in" => ValueTypeConditionResolver.Operator.OutOfRange, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for value type.") - }; - } - - private static BoolConditionResolver.Operator ParseBoolOperator(string operatorStr) - { - return operatorStr switch - { - "is" => BoolConditionResolver.Operator.Is, - "==" => BoolConditionResolver.Operator.Is, - "equals" => BoolConditionResolver.Operator.Is, - //"isFalse" => BoolConditionNode.Operator.IsFalse, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for bool type.") - }; - } - - private static StringConditionResolver.Operator ParseStringOperator(string operatorStr) - { - return operatorStr switch - { - "c" => StringConditionResolver.Operator.Contains, - "nc" => StringConditionResolver.Operator.DoesNotContain, - "sw" => StringConditionResolver.Operator.StartsWith, - "ew" => StringConditionResolver.Operator.EndsWith, - - "contains" => StringConditionResolver.Operator.Contains, - "doesNotContain" => StringConditionResolver.Operator.DoesNotContain, - "equals" => StringConditionResolver.Operator.Equal, - "==" => StringConditionResolver.Operator.Equal, - "notEquals" => StringConditionResolver.Operator.NotEqual, - "!=" => StringConditionResolver.Operator.NotEqual, - "startsWith" => StringConditionResolver.Operator.StartsWith, - "endsWith" => StringConditionResolver.Operator.EndsWith, - _ => throw new ArgumentException($"Invalid operator {operatorStr} for string type.") - }; - } - } - -} diff --git a/NodeFlow/Tool/SerinExpression/SerinExpressionEvaluator.cs b/NodeFlow/Tool/SerinExpression/SerinExpressionEvaluator.cs deleted file mode 100644 index 99666ea..0000000 --- a/NodeFlow/Tool/SerinExpression/SerinExpressionEvaluator.cs +++ /dev/null @@ -1,216 +0,0 @@ -using System.Data; - -namespace Serein.NodeFlow.Tool.SerinExpression -{ - public class SerinArithmeticExpressionEvaluator - { - private static readonly DataTable table = new DataTable(); - - public static double Evaluate(string expression, double inputValue) - { - // 替换占位符@为输入值 - expression = expression.Replace("@", inputValue.ToString()); - try - { - // 使用 DataTable.Compute 方法计算表达式 - var result = table.Compute(expression, string.Empty); - return Convert.ToDouble(result); - } - catch - { - throw new ArgumentException("Invalid arithmetic expression."); - } - } - } - - public class SerinExpressionEvaluator - { - /// - /// - /// - /// 表达式 - /// 操作对象 - /// 是否改变了对象(get语法) - /// - /// - /// - public static object Evaluate(string expression, object targetObJ, out bool isChange) - { - var parts = expression.Split([' '], 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid expression format."); - } - - var operation = parts[0].ToLower(); - var operand = parts[1][0] == '.' ? parts[1][1..] : parts[1]; - - var result = operation switch - { - "@num" => ComputedNumber(targetObJ, operand), - "@call" => InvokeMethod(targetObJ, operand), - "@get" => GetMember(targetObJ, operand), - "@set" => SetMember(targetObJ, operand), - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - isChange = operation switch - { - "@num" => true, - "@call" => true, - "@get" => true, - "@set" => false, - _ => throw new NotSupportedException($"Operation {operation} is not supported.") - }; - - return result; - } - - - private static readonly char[] separator = ['(', ')']; - private static readonly char[] separatorArray = [',']; - - private static object InvokeMethod(object target, string methodCall) - { - var methodParts = methodCall.Split(separator, StringSplitOptions.RemoveEmptyEntries); - if (methodParts.Length != 2) - { - throw new ArgumentException("Invalid method call format."); - } - - var methodName = methodParts[0]; - var parameterList = methodParts[1]; - var parameters = parameterList.Split(separatorArray, StringSplitOptions.RemoveEmptyEntries) - .Select(p => p.Trim()) - .ToArray(); - - var method = target.GetType().GetMethod(methodName); - if (method == null) - { - throw new ArgumentException($"Method {methodName} not found on target."); - } - - var parameterValues = method.GetParameters() - .Select((p, index) => Convert.ChangeType(parameters[index], p.ParameterType)) - .ToArray(); - - - return method.Invoke(target, parameterValues); - - } - - private static object GetMember(object target, string memberPath) - { - var members = memberPath.Split('.'); - foreach (var member in members) - { - - if (target == null) return null; - - - var property = target.GetType().GetProperty(member); - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - - return target; - - } - - private static object SetMember(object target, string assignment) - { - var parts = assignment.Split(new[] { '=' }, 2); - if (parts.Length != 2) - { - throw new ArgumentException("Invalid assignment format."); - } - - var memberPath = parts[0].Trim(); - var value = parts[1].Trim(); - - var members = memberPath.Split('.'); - for (int i = 0; i < members.Length - 1; i++) - { - var member = members[i]; - - var property = target.GetType().GetProperty(member); - - if (property != null) - { - - target = property.GetValue(target); - - } - else - { - var field = target.GetType().GetField(member); - if (field != null) - { - - target = field.GetValue(target); - - } - else - { - throw new ArgumentException($"Member {member} not found on target."); - } - } - } - - var lastMember = members.Last(); - - var lastProperty = target.GetType().GetProperty(lastMember); - - if (lastProperty != null) - { - var convertedValue = Convert.ChangeType(value, lastProperty.PropertyType); - lastProperty.SetValue(target, convertedValue); - } - else - { - var lastField = target.GetType().GetField(lastMember); - if (lastField != null) - { - var convertedValue = Convert.ChangeType(value, lastField.FieldType); - lastField.SetValue(target, convertedValue); - } - else - { - throw new ArgumentException($"Member {lastMember} not found on target."); - } - } - - return target; - } - - private static double ComputedNumber(object value, string expression) - { - double numericValue = Convert.ToDouble(value); - if (!string.IsNullOrEmpty(expression)) - { - numericValue = SerinArithmeticExpressionEvaluator.Evaluate(expression, numericValue); - } - - return numericValue; - } - } -} diff --git a/NodeFlow/Tool/TcsSignal.cs b/NodeFlow/Tool/TcsSignal.cs deleted file mode 100644 index 2057ab4..0000000 --- a/NodeFlow/Tool/TcsSignal.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Collections.Concurrent; -using Serein.NodeFlow; -using Serein.NodeFlow.Model; - -namespace Serein.NodeFlow.Tool -{ - public class TcsSignalException : Exception - { - public FlowStateType FsState { get; set; } - public TcsSignalException(string? message) : base(message) - { - FsState = FlowStateType.Error; - } - } - - public class TcsSignal where TSignal : struct, Enum - { - //public ConcurrentDictionary>> TcsEvent { get; } = new(); - public ConcurrentDictionary> TcsEvent { get; } = new(); - - public ConcurrentDictionary TcsLock { get; } = new(); - - /// - /// 触发信号 - /// - /// - /// 信号 - /// 传递的参数 - /// 是否成功触发 - public bool TriggerSignal(TSignal signal, T value) - { - var tcsLock = TcsLock.GetOrAdd(signal, new object()); - lock (tcsLock) - { - if (TcsEvent.TryRemove(signal, out var waitTcs)) - { - waitTcs.SetResult(value); - return true; - } - return false; - } - } - - public TaskCompletionSource CreateTcs(TSignal signal) - { - var tcsLock = TcsLock.GetOrAdd(signal, new object()); - lock (tcsLock) - { - var tcs = TcsEvent.GetOrAdd(signal, new TaskCompletionSource()); - return tcs; - } - - } - - public void CancelTask() - { - foreach (var tcs in TcsEvent.Values) - { - tcs.SetException(new TcsSignalException("任务取消")); - } - TcsEvent.Clear(); - } - } -}