A:补充部分缺失功能

U:调整元信息数据
This commit is contained in:
jimmy committed 2026-01-21 13:55:53 +08:00
1 parent b15e57d150
commit 4973979169
15 files changed
+177 -65

No files matched your search

+4 -4
View File
@@ -2,17 +2,17 @@
## Project Structure & Module Organization ## Project Structure & Module Organization
- Solution: `Sharp.sln` aggregates all modules in this folder. - Solution: `Sharp.sln` aggregates all modules in this folder.
- Libraries: `Common`, `Config`, `Log`, `EventBus`, `Sharp.Infrastructure`. - Libraries: `Common`, `Config`, `Log`, `Cache`, `EventBus`, `Data`, `NetServer`, `NetClient`, `Ports`, `Plc`, `Plc.Siemens`, `Process`, `Python`, `Wpf`, `Wpf.HandyControl`, `Wpf.DevTools`.
- Networking: `NetServer` (HTTP server + middleware), `NetClient` (typed HTTP client). - Networking: `NetServer` (HTTP server + middleware), `NetClient` (typed HTTP client).
- UI: `Wpf` (shared WPF helpers), `Client` (WPF app using `Wpf`). - UI: `Wpf` (shared WPF helpers), `Wpf.HandyControl`, `Wpf.DevTools`, `Sharp.Demo` (WPF demo app).
- Examples: `NetServer/Examples` contains a runnable sample entry point. - Examples: `NetServer/Examples` contains a runnable sample entry point.
- Tests: solution includes external projects under `../../test/*` (e.g., `Common.Test`, `NetClient.Test`). - Tests: solution includes external projects under `../../test/*` (e.g., `Common.Test`, `NetClient.Test`).
## Build, Test, and Development Commands ## Build, Test, and Development Commands
- Restore: `dotnet restore` - Restore: `dotnet restore`
- Build (Debug/Release): `dotnet build Sharp.sln -c Debug` | `-c Release` - Build (Debug/Release): `dotnet build Sharp.sln -c Debug` | `-c Release`
- Run server example: `dotnet run --project NetServer/NetServer.csproj` - Run server example: `dotnet run --project NetServer/Examples/NetServer.Examples.csproj`
- Run WPF client (Windows): `dotnet run --project Client/Client.csproj` - Run WPF demo (Windows): `dotnet run --project Sharp.Demo/Sharp.Demo.csproj`
- Run all tests: `dotnet test Sharp.sln -c Debug --no-build` - Run all tests: `dotnet test Sharp.sln -c Debug --no-build`
- Run a single test project: `dotnet test ../../test/Common.Test/Common.Test.csproj` - Run a single test project: `dotnet test ../../test/Common.Test/Common.Test.csproj`
+1 -1
View File
@@ -8,7 +8,7 @@
<RootNamespace>Sharp.Cache</RootNamespace> <RootNamespace>Sharp.Cache</RootNamespace>
<!-- 程序集元数据 --> <!-- 程序集元数据 -->
<Description>Sharp Framework 缓存库 - 内存缓存抽象和实现(规划中)</Description> <Description>Sharp Framework 缓存库 - 内存缓存抽象和实现</Description>
<!-- NuGet 包元数据 --> <!-- NuGet 包元数据 -->
<PackageTags>sharp;cache;memory-cache;caching</PackageTags> <PackageTags>sharp;cache;memory-cache;caching</PackageTags>
+3 -7
View File
@@ -1,7 +1,5 @@
# Sharp.Cache # Sharp.Cache
> **🚧 开发中 / Under Construction**
轻量级内存缓存模块,基于 `Microsoft.Extensions.Caching.Memory`,提供简洁的缓存API。 轻量级内存缓存模块,基于 `Microsoft.Extensions.Caching.Memory`,提供简洁的缓存API。
## 📋 为什么需要 Cache? ## 📋 为什么需要 Cache?
@@ -72,7 +70,7 @@ public class ProductService {
--- ---
## 🚀 快速开始(未来) ## 🚀 快速开始
### 1. 注册服务 ### 1. 注册服务
@@ -646,7 +644,5 @@ public async Task<Result<Product>> GetProductAsync(int id) {
--- ---
**状态**:设计阶段,未实现 **状态**:已实现(内存缓存)
**预计实现时间**:根据实际需求决定 **当前实现**:IMemoryCache 封装 + 绝对/滑动过期 + 前缀移除
**实现难度**:低(100行代码即可完成核心功能)
**依赖**:Microsoft.Extensions.Caching.Memory(.NET内置)
+22
View File
@@ -0,0 +1,22 @@
<Project>
<PropertyGroup>
<Authors Condition="'$(Authors)' == ''">duyl328</Authors>
<PackageProjectUrl Condition="'$(PackageProjectUrl)' == ''">https://seyl.me</PackageProjectUrl>
<PackageLicenseFile Condition="'$(PackageLicenseFile)' == ''">LICENSE</PackageLicenseFile>
<PackageReadmeFile Condition="'$(PackageReadmeFile)' == ''">README.md</PackageReadmeFile>
<PackageRequireLicenseAcceptance Condition="'$(PackageRequireLicenseAcceptance)' == ''">false</PackageRequireLicenseAcceptance>
<Version Condition="'$(Version)' == ''">1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)../../LICENSE"
Pack="true"
PackagePath=""
Link="LICENSE"
Condition="Exists('$(MSBuildThisFileDirectory)../../LICENSE')" />
<None Update="README.md"
Pack="true"
PackagePath=""
Condition="Exists('$(MSBuildProjectDirectory)/README.md')" />
</ItemGroup>
</Project>
+1 -1
View File
@@ -8,7 +8,7 @@
<RootNamespace>Sharp.EventBus</RootNamespace> <RootNamespace>Sharp.EventBus</RootNamespace>
<!-- 程序集元数据 --> <!-- 程序集元数据 -->
<Description>Sharp Framework 事件总线库 - 进程内事件发布/订阅(规划中)</Description> <Description>Sharp Framework 事件总线库 - 进程内事件发布/订阅</Description>
<!-- NuGet 包元数据 --> <!-- NuGet 包元数据 -->
<PackageTags>sharp;eventbus;pub-sub;events</PackageTags> <PackageTags>sharp;eventbus;pub-sub;events</PackageTags>
+3 -6
View File
@@ -1,7 +1,5 @@
# Sharp.EventBus # Sharp.EventBus
> **🚧 开发中 / Under Construction**
轻量级进程内事件总线,用于解耦应用程序中的模块通信。 轻量级进程内事件总线,用于解耦应用程序中的模块通信。
## 📋 为什么需要 EventBus? ## 📋 为什么需要 EventBus?
@@ -74,7 +72,7 @@ public class PlcDataLogger {
--- ---
## 🚀 快速开始(未来) ## 🚀 快速开始
### 1. 注册服务 ### 1. 注册服务
@@ -472,6 +470,5 @@ System.Threading.Channels.Channel<EventEnvelope>
--- ---
**状态**:设计阶段,未实现 **状态**:已实现(进程内 InMemoryEventBus)
**预计实现时间**:根据实际需求决定 **当前实现**:基于 Channel 的异步队列 + 订阅优先级/过滤
**当前替代方案**:使用 Common 模块的 Global 容器 + 委托事件
+7 -7
View File
@@ -1,7 +1,7 @@
# Sharp Project Context # Sharp Project Context
## Project Overview ## Project Overview
**Sharp** is a modular C# .NET 8 solution designed for industrial automation and network services. It features a "Spring Boot-like" HTTP server framework, a robust PLC communication library, and WPF-based client/server applications. The architecture emphasizes dependency injection, functional error handling (Result pattern), and clean separation of concerns. **Sharp** is a modular C# .NET 8 solution designed for industrial automation and network services. It features a "Spring Boot-like" HTTP server framework, a robust PLC communication library, and WPF UI libraries with a demo application. The architecture emphasizes dependency injection, functional error handling (Result pattern), and clean separation of concerns.
## Key Modules ## Key Modules
@@ -20,9 +20,10 @@
- **Ports**: Serial/COM port abstractions. - **Ports**: Serial/COM port abstractions.
### Applications (UI) ### Applications (UI)
- **Client**: Main WPF Client application. - **Sharp.Demo**: WPF demo application showcasing key modules.
- **Server**: WPF Server application (likely a dashboard or local control interface).
- **Wpf**: Shared WPF UI logic, behaviors, and converters. - **Wpf**: Shared WPF UI logic, behaviors, and converters.
- **Wpf.HandyControl**: HandyControl integration and dialog services.
- **Wpf.DevTools**: WPF developer tooling (visual tree/log/perf).
## Development Workflow ## Development Workflow
@@ -39,14 +40,13 @@
```bash ```bash
dotnet build Sharp.sln -c Debug dotnet build Sharp.sln -c Debug
``` ```
- **Run WPF Client**: - **Run WPF Demo**:
```bash ```bash
dotnet run --project Client/Client.csproj dotnet run --project Sharp.Demo/Sharp.Demo.csproj
``` ```
- **Run NetServer Example**: - **Run NetServer Example**:
```bash ```bash
dotnet run --project NetServer/Examples dotnet run --project NetServer/Examples/NetServer.Examples.csproj
# Note: Check specific project path if Examples is a folder or project
``` ```
### Testing ### Testing
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Sharp.NetServer.Examples</AssemblyName>
<RootNamespace>Sharp.NetServer.Examples</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NetServer.csproj" />
</ItemGroup>
</Project>
+4
View File
@@ -18,6 +18,10 @@
<ProjectReference Include="..\Config\Config.csproj"/> <ProjectReference Include="..\Config\Config.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Remove="Examples/**"/>
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0"/> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0"/>
+14 -14
View File
@@ -10,11 +10,11 @@
- **[Sharp.Common](Common/README.md)**: 基础工具库。提供轻量级 DI 容器 (`Global`)、函数式结果模式 (`Result<T>`)、以及丰富的扩展方法(String, DateTime, Encryption, Reflection)。 - **[Sharp.Common](Common/README.md)**: 基础工具库。提供轻量级 DI 容器 (`Global`)、函数式结果模式 (`Result<T>`)、以及丰富的扩展方法(String, DateTime, Encryption, Reflection)。
- **[Sharp.Config](Config/README.md)**: 强大的配置管理。支持 JSON/XML/INI/TOML 多源聚合、强类型绑定和数据注解验证。 - **[Sharp.Config](Config/README.md)**: 强大的配置管理。支持 JSON/XML/INI/TOML 多源聚合、强类型绑定和数据注解验证。
- **[Sharp.Log](Log/README.md)**: 统一日志门面。基于 Serilog 封装,支持一行代码接入,提供结构化日志和文件滚动策略。 - **[Sharp.Log](Log/README.md)**: 统一日志门面。基于 Serilog 封装,支持一行代码接入,提供结构化日志和文件滚动策略。
- **[Sharp.EventBus](EventBus/README.md)**: (开发中) 轻量级事件总线。 - **[Sharp.EventBus](EventBus/README.md)**: 轻量级事件总线。
- **[Sharp.Cache](Cache/README.md)**: 轻量级内存缓存抽象与实现。
### 💾 数据与存储 ### 💾 数据与存储
- **[Sharp.Data](Data/README.md)**: 极简数据访问层。基于 EF Core,提供开箱即用的仓储模式、自动审计(创建人/时间)、软删除和分页支持。 - **[Sharp.Data](Data/README.md)**: 极简数据访问层。基于 EF Core,提供仓储模式、自动审计(创建人/时间)、软删除和分页支持,兼容多种数据库。
- **[Sharp.Repository](Repository/README.md)**: 数据库集成模块。通过配置切换 SQL Server/MySQL/PostgreSQL/Sqlite,支持自动迁移。
### 🌐 网络与通信 ### 🌐 网络与通信
- **[Sharp.NetServer](NetServer/README.md)**: 轻量级 Web 框架。基于 `HttpListener`,提供类似 ASP.NET Core 的 Controller/Route/Middleware 开发体验,适合嵌入式或桌面应用内嵌 Web 服务。 - **[Sharp.NetServer](NetServer/README.md)**: 轻量级 Web 框架。基于 `HttpListener`,提供类似 ASP.NET Core 的 Controller/Route/Middleware 开发体验,适合嵌入式或桌面应用内嵌 Web 服务。
@@ -27,8 +27,13 @@
### 🖥️ 桌面应用 UI ### 🖥️ 桌面应用 UI
- **[Sharp.Wpf](Wpf/README.md)**: WPF 基础库。提供 MVVM 基类、全局异常捕获、常用转换器、对话框服务和行为扩展。 - **[Sharp.Wpf](Wpf/README.md)**: WPF 基础库。提供 MVVM 基类、全局异常捕获、常用转换器、对话框服务和行为扩展。
- **[Sharp.Client](Client/README.md)**: 综合客户端示例。集成 PLC 监控、串口调试和用户登录功能的工业控制台应用。 - **[Sharp.Wpf.HandyControl](Wpf.HandyControl/README.md)**: HandyControl 组件库集成与对话框服务。
- **[Sharp.Server](Server/README.md)**: 服务器控制台示例。展示了如何在一个 WPF 应用中托管 NetServer Web 服务,并提供可视化管理界面。 - **[Sharp.Wpf.DevTools](Wpf.DevTools/README.md)**: WPF 开发者工具库(可视化树、日志、性能监控)。
- **[Sharp.Demo](Sharp.Demo/README.md)**: 综合演示应用,覆盖主要模块用法。
### 🧩 工具与集成
- **[Sharp.Process](Process/README.md)**: 外部进程执行、管理和监控。
- **[Sharp.Python](Python/README.md)**: Python 脚本执行与互操作。
## 🚀 快速开始 ## 🚀 快速开始
@@ -47,19 +52,14 @@ dotnet build Sharp.sln -c Debug
### 运行示例 ### 运行示例
**1. 运行 WPF 客户端:** **1. 运行 WPF 综合演示:**
```bash ```bash
dotnet run --project Client/Client.csproj dotnet run --project Sharp.Demo/Sharp.Demo.csproj
``` ```
**2. 运行嵌入式 Web 服务器:** **2. 运行 NetServer 纯控制台示例:**
```bash ```bash
dotnet run --project Server/Server.csproj dotnet run --project NetServer/Examples/NetServer.Examples.csproj
```
**3. 运行 NetServer 纯控制台示例:**
```bash
dotnet run --project NetServer/Examples
``` ```
## 🧪 测试 ## 🧪 测试
+1 -6
View File
@@ -8,20 +8,15 @@
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<AssemblyName>Sharp.Demo</AssemblyName> <AssemblyName>Sharp.Demo</AssemblyName>
<RootNamespace>Sharp.Demo</RootNamespace> <RootNamespace>Sharp.Demo</RootNamespace>
<IsPackable>false</IsPackable>
<!-- 程序集元数据 --> <!-- 程序集元数据 -->
<Description>Sharp Framework 综合演示应用 - 展示所有模块的最佳实践和使用方式</Description> <Description>Sharp Framework 综合演示应用 - 展示所有模块的最佳实践和使用方式</Description>
<!-- NuGet 包元数据 --> <!-- NuGet 包元数据 -->
<PackageTags>sharp;demo;wpf;framework;example;best-practices</PackageTags> <PackageTags>sharp;demo;wpf;framework;example;best-practices</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup> </PropertyGroup>
<!-- 包含 README 到 NuGet 包 -->
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\"/>
</ItemGroup>
<!-- NuGet 包 --> <!-- NuGet 包 -->
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
@@ -0,0 +1,43 @@
<Window x:Class="Sharp.Wpf.HandyControl.Dialogs.InputDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="输入"
Width="420"
SizeToContent="Height"
WindowStartupLocation="CenterOwner"
ResizeMode="NoResize">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock x:Name="MessageText"
TextWrapping="Wrap"
Margin="0,0,0,10" />
<TextBox x:Name="InputTextBox"
Grid.Row="1"
Height="32"
Padding="6,0"
MinWidth="300" />
<StackPanel Grid.Row="2"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,15,0,0">
<Button x:Name="OkButton"
Content="确定"
Width="90"
Margin="0,0,10,0"
IsDefault="True"
Click="OkButton_Click" />
<Button x:Name="CancelButton"
Content="取消"
Width="90"
IsCancel="True"
Click="CancelButton_Click" />
</StackPanel>
</Grid>
</Window>
@@ -0,0 +1,31 @@
using System.Windows;
namespace Sharp.Wpf.HandyControl.Dialogs;
public partial class InputDialog : Window
{
public string InputValue => InputTextBox.Text;
public InputDialog(string message, string? title = null, string? defaultValue = null)
{
InitializeComponent();
Title = string.IsNullOrWhiteSpace(title) ? "输入" : title;
MessageText.Text = message;
InputTextBox.Text = defaultValue ?? string.Empty;
Loaded += (_, _) =>
{
InputTextBox.Focus();
InputTextBox.SelectAll();
};
}
private void OkButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
}
}
+4 -14
View File
@@ -304,7 +304,7 @@ public interface IHandyDialogService : IDialogService
Task<HandyDialogResult> AskAsync(string message, string? title = null); Task<HandyDialogResult> AskAsync(string message, string? title = null);
/// <summary> /// <summary>
/// 显示输入对话框(尚未实现) /// 显示输入对话框
/// </summary> /// </summary>
Task<Result<string>> ShowInputAsync(string message, string? title = null, string? defaultValue = null); Task<Result<string>> ShowInputAsync(string message, string? title = null, string? defaultValue = null);
@@ -1037,19 +1037,9 @@ services.AddSharpHandyControl();
services.AddSingleton<IDialogService, MyCustomDialogService>(); services.AddSingleton<IDialogService, MyCustomDialogService>();
``` ```
### Q5: `ShowInputAsync` 为什么返回失败? ### Q5: `ShowInputAsync` 如何返回结果?
**A:** `ShowInputAsync` 功能尚未实现(需要自定义对话框窗口),当前版本会返回: **A:** `ShowInputAsync` 会弹出输入对话框,点击“确定”返回 `Result.Success`,点击“取消”返回失败结果(错误信息为“用户取消输入”)。
```csharp
Result.Failure<string>("输入对话框功能尚未实现,需要自定义对话框窗口")
```
如果需要输入功能,可以临时使用:
- 创建自定义 Window 进行输入
- 使用 HandyControl 的其他输入控件
- 等待后续版本实现
### Q6: 能否在 WinForms 项目中使用? ### Q6: 能否在 WinForms 项目中使用?
@@ -1217,7 +1207,7 @@ protected override void OnStartup(StartupEventArgs e)
|------------------------------------------------|------------|---------------------------|--------| |------------------------------------------------|------------|---------------------------|--------|
| `ConfirmAsync(message, title)` | 确认对话框 | `Task<bool>` | 确定/取消 | | `ConfirmAsync(message, title)` | 确认对话框 | `Task<bool>` | 确定/取消 |
| `AskAsync(message, title)` | 询问对话框 | `Task<HandyDialogResult>` | 是/否/取消 | | `AskAsync(message, title)` | 询问对话框 | `Task<HandyDialogResult>` | 是/否/取消 |
| `ShowInputAsync(message, title, defaultValue)` | 输入对话框(未实现) | `Task<Result<string>>` | 确定/取消 | | `ShowInputAsync(message, title, defaultValue)` | 输入对话框 | `Task<Result<string>>` | 确定/取消 |
### Growl 通知方法 ### Growl 通知方法
@@ -2,6 +2,7 @@ using System.Windows;
using Common.Results; using Common.Results;
using HandyControl.Controls; using HandyControl.Controls;
using HandyControl.Data; using HandyControl.Data;
using Sharp.Wpf.HandyControl.Dialogs;
using Sharp.Wpf.HandyControl.Options; using Sharp.Wpf.HandyControl.Options;
using Sharp.Wpf.Services; using Sharp.Wpf.Services;
using MessageBox = HandyControl.Controls.MessageBox; using MessageBox = HandyControl.Controls.MessageBox;
@@ -96,13 +97,29 @@ public class HandyDialogService : IHandyDialogService
} }
/// <summary> /// <summary>
/// 显示输入对话框(尚未实现) /// 显示输入对话框
/// </summary> /// </summary>
public Task<Result<string>> ShowInputAsync(string message, string? title = null, string? defaultValue = null) public Task<Result<string>> ShowInputAsync(string message, string? title = null, string? defaultValue = null)
{ {
// TODO: 需要自定义 TextDialog 窗口来实现此功能 return Task.Run(() =>
// 当前版本暂不支持,返回失败结果 {
return Task.FromResult(Result.Failure<string>("输入对话框功能尚未实现,需要自定义对话框窗口")); if (Application.Current == null)
return Result.Failure<string>("当前应用上下文不可用");
return Application.Current.Dispatcher.Invoke(() =>
{
var dialog = new InputDialog(message, title, defaultValue)
{
Owner = Application.Current.MainWindow
};
var dialogResult = dialog.ShowDialog();
if (dialogResult == true)
return Result.Success(dialog.InputValue);
return Result.Failure<string>("用户取消输入");
});
});
} }
/// <summary> /// <summary>
@@ -178,4 +195,4 @@ public class HandyDialogService : IHandyDialogService
} }
#endregion #endregion
} }