From 86da5b3ba6e29143a0a64ff6814c9a4a012ee717 Mon Sep 17 00:00:00 2001
From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com>
Date: Tue, 17 Sep 2024 15:58:37 +0800
Subject: [PATCH] =?UTF-8?q?=E5=86=85=E7=BD=AE=E4=BA=86Web=20Server/IRouter?=
=?UTF-8?q?=E7=9A=84http=20api=E8=AF=B7=E6=B1=82=E5=A4=84=E7=90=86?=
=?UTF-8?q?=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Serein.Library.Framework.csproj | 2 +-
Library/Api/IFlowEnvironment.cs | 4 +-
Library/Serein.Library.csproj | 2 +-
Library/Utils/SereinIoc.cs | 37 ++++++++++++++----
Library/Web/QueryStringParser.cs | 39 +++++++++++++++++++
Library/Web/Router.cs | 19 ++++++---
.../Web/{WebAPIAttribute.cs => WebServer.cs} | 23 ++++++++++-
NodeFlow/FlowStarter.cs | 8 ++++
WorkBench/App.xaml.cs | 16 ++++----
9 files changed, 123 insertions(+), 27 deletions(-)
create mode 100644 Library/Web/QueryStringParser.cs
rename Library/Web/{WebAPIAttribute.cs => WebServer.cs} (88%)
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)!;
+ //}
}
}