diff --git a/Library.Framework/Serein.Library.Framework.csproj b/Library.Framework/Serein.Library.Framework.csproj index 6bbbe58..9a4e167 100644 --- a/Library.Framework/Serein.Library.Framework.csproj +++ b/Library.Framework/Serein.Library.Framework.csproj @@ -55,7 +55,7 @@ - {55C77D23-2FD3-43D1-918C-DC3DE9614F0F} + {9FCE93C2-2278-46F3-96AB-CDAAFF27A55F} Serein.Library diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index 42c970c..57e5bf1 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -229,9 +229,9 @@ namespace Serein.Library.Api /// /// 加载项目文件 /// - /// + /// /// - void LoadProject(SereinProjectData project, string filePath); + void LoadProject(SereinProjectData projectFile, string filePath); /// /// 从文件中加载Dll /// diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index 0c08942..bd3f82b 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;net461 D:\Project\C#\DynamicControl\SereinFlow\.Output diff --git a/Library/Utils/SereinIoc.cs b/Library/Utils/SereinIoc.cs index b40c2b2..012c6cf 100644 --- a/Library/Utils/SereinIoc.cs +++ b/Library/Utils/SereinIoc.cs @@ -91,32 +91,53 @@ namespace Serein.Library.Utils var typeFullName = typeof(TService).FullName; RegisterType(typeFullName, typeof(TImplementation)); return this; - } + } #endregion /// - /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。 + /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。 /// public object GetOrRegisterInstantiate(Type type) { // 尝试从容器中获取对象 if (!_dependencies.TryGetValue(type.FullName, out object value)) { - Register(type);// 注册类型信息 - value = Instantiate(type); // 创建实例对象,并注入依赖 - _dependencies.TryAdd(type.FullName, value); // 登记到IOC容器中 + // 容器中不存在目标类型的对象 + if (type.IsInterface) + { + if (_typeMappings.TryGetValue(type.FullName, out Type implementationType)) + { + // 是接口类型,存在注册信息 + Register(type);// 注册类型信息 + value = Instantiate(implementationType); // 创建实例对象,并注入依赖 + _dependencies.TryAdd(type.FullName, value); // 登记到IOC容器中 + _typeMappings.TryRemove(type.FullName, out _); // 取消类型的注册信息 + } + else + { + //需要获取接口类型的实例,但不存在类型注册信息 + Console.WriteLine("当前需要获取接口,但没有注册实现类的类型,无法创建接口实例"); + return null; + } + } + else + { + // 不是接口,直接注册 + Register(type);// 注册类型信息 + value = Instantiate(type); // 创建实例对象,并注入依赖 + _dependencies.TryAdd(type.FullName, value); // 登记到IOC容器中 + } } return value; } /// - /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。 + /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。 /// public T GetOrRegisterInstantiate() { - var value = Instantiate(typeof(T)); - return (T)value; + return (T)GetOrRegisterInstantiate(typeof(T)); } /// diff --git a/Library/Web/QueryStringParser.cs b/Library/Web/QueryStringParser.cs new file mode 100644 index 0000000..900ab79 --- /dev/null +++ b/Library/Web/QueryStringParser.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Serein.Library.Web +{ + internal class QueryStringParser + { + public static Dictionary ParseQueryString(string query) + { + var result = new Dictionary(); + + if (string.IsNullOrEmpty(query)) + return result; + + // 如果字符串以'?'开头,移除它 + if (query.StartsWith("?")) + query = query.Substring(1); + + // 拆分键值对 + var pairs = query.Split('&'); + foreach (var pair in pairs) + { + // 忽略空的键值对 + if (string.IsNullOrEmpty(pair)) continue; + + // 用等号分隔键和值 + var keyValue = pair.Split(new[] { '=' }, 2); + + var key = Uri.UnescapeDataString(keyValue[0]); // 解码键 + var value = keyValue.Length > 1 ? Uri.UnescapeDataString(keyValue[1]) : string.Empty; // 解码值 + + result[key] = value; // 添加到字典中 + } + + return result; + } + } +} diff --git a/Library/Web/Router.cs b/Library/Web/Router.cs index f4c5e26..c5531d8 100644 --- a/Library/Web/Router.cs +++ b/Library/Web/Router.cs @@ -137,8 +137,9 @@ namespace Serein.Library.Web if (!controllerType.IsClass || controllerType.IsAbstract) return false; // 如果不是类或者是抽象类,则直接返回 var autoHostingAttribute = controllerType.GetCustomAttribute(); + var methods = controllerType.GetMethods().Where(m => m.GetCustomAttribute() != null).ToArray(); - foreach (var method in controllerType.GetMethods()) // 遍历控制器类型的所有方法 + foreach (var method in methods) // 遍历控制器类型的所有方法 { var routeAttribute = method.GetCustomAttribute(); // 获取方法上的 WebAPIAttribute 自定义属性 if (routeAttribute != null) // 如果存在 WebAPIAttribute 属性 @@ -354,6 +355,7 @@ namespace Serein.Library.Web { return value; } +#pragma warning restore CS0168 // 声明了变量,但从未使用过 } /// @@ -507,12 +509,17 @@ namespace Serein.Library.Web if (pathParts.Length > 1) // 如果包含查询字符串 { - var queryParams = HttpUtility.ParseQueryString(pathParts[1]); // 解析查询字符串 - - foreach (string key in queryParams) // 遍历查询字符串的键值对 + //var queryParams = HttpUtility.ParseQueryString(pathParts[1]); // 解析查询字符串 + //foreach (string key in queryParams) // 遍历查询字符串的键值对 + //{ + // if (key == null) continue; + // routeValues[key] = queryParams[key]; // 将键值对添加到路由参数字典中 + //} + var parsedQuery = QueryStringParser.ParseQueryString(pathParts[1]); + foreach (var kvp in parsedQuery) { - if (key == null) continue; - routeValues[key] = queryParams[key]; // 将键值对添加到路由参数字典中 + //Console.WriteLine($"{kvp.Key}: {kvp.Value}"); + routeValues[kvp.Key] = kvp.Value; // 将键值对添加到路由参数字典中 } } diff --git a/Library/Web/WebAPIAttribute.cs b/Library/Web/WebServer.cs similarity index 88% rename from Library/Web/WebAPIAttribute.cs rename to Library/Web/WebServer.cs index 5079125..eb7cf81 100644 --- a/Library/Web/WebAPIAttribute.cs +++ b/Library/Web/WebServer.cs @@ -1,4 +1,6 @@ using Serein.Library.Api; +using Serein.Library.Attributes; +using Serein.Library.Utils; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -13,9 +15,12 @@ namespace Serein.Library.Web /// public class WebServer { - [AutoHosting] + [AutoInjection] public IRouter Router { get; set; } // 路由器 + [AutoInjection] + public NodeRunCts nodeRunCts { get; set; } + private HttpListener listener; // HTTP 监听器 private RequestLimiter requestLimiter; //接口防刷 @@ -38,6 +43,21 @@ namespace Serein.Library.Web listener.Start(); // 开始监听 + //_ = Task.Run(async () => + //{ + // while (true) + // { + // await Task.Delay(100); + // if (nodeRunCts.IsCancellationRequested) + // { + + // } + + // var context = await listener.GetContextAsync(); // 获取请求上下文 + // ProcessRequestAsync(context); // 处理请求 + // } + //}); + Task.Run(async () => { while (listener.IsListening) @@ -46,6 +66,7 @@ namespace Serein.Library.Web ProcessRequestAsync(context); // 处理请求 } }); + return this; } diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs index 2d87596..d68ad31 100644 --- a/NodeFlow/FlowStarter.cs +++ b/NodeFlow/FlowStarter.cs @@ -3,6 +3,7 @@ using Serein.Library.Core.NodeFlow; using Serein.Library.Entity; using Serein.Library.Enums; using Serein.Library.Utils; +using Serein.Library.Web; using Serein.NodeFlow.Base; using Serein.NodeFlow.Model; @@ -173,6 +174,10 @@ namespace Serein.NodeFlow Context.SereinIoc.Build(); // 预防有人在加载时才注册类型,再绑定一次 ExitAction = () => { + SereinIOC.Run(web => { + web?.Stop(); + }); + foreach (MethodDetails? md in exitMethods) { object?[]? data = [md.ActingInstance, args]; @@ -188,6 +193,9 @@ namespace Serein.NodeFlow } FlowState = RunState.Completion; FlipFlopState = RunState.Completion; + + + }; #endregion diff --git a/WorkBench/App.xaml.cs b/WorkBench/App.xaml.cs index b3becc3..5b27782 100644 --- a/WorkBench/App.xaml.cs +++ b/WorkBench/App.xaml.cs @@ -150,14 +150,14 @@ namespace Serein.WorkBench Shutdown(); // 关闭应用程序 } } - //else if (1 == 1) - //{ - // string filePath = @"F:\临时\project\new project.dnf"; - // //string filePath = @"D:\Project\C#\DynamicControl\SereinFlow\.Output\Debug\net8.0-windows7.0\U9 project.dnf"; - // string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容 - // App.FData = JsonConvert.DeserializeObject(content); - // App.FileDataPath = filePath;//System.IO.Path.GetDirectoryName(filePath)!; - //} + //else if (1 == 1) + //{ + // string filePath = @"F:\临时\project\new project.dnf"; + // //string filePath = @"D:\Project\C#\DynamicControl\SereinFlow\.Output\Debug\net8.0-windows7.0\U9 project.dnf"; + // string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容 + // App.FData = JsonConvert.DeserializeObject(content); + // App.FileDataPath = filePath;//System.IO.Path.GetDirectoryName(filePath)!; + //} } }