docs: 补全全部缺失的 XML 文档注释(中文)

- 为全部 5 个项目(Avalonia-API、Avalonia-Common、Avalonia-EFCore、
  Avalonia-PC、Avalonia-Services)中缺失注释的类、方法、属性、字段、
  接口成员等补全中文 XML 文档注释
- 共修改约 37 个文件,补全约 220+ 处注释
- 修复 ServiceEndpointCollection.cs 中 MapDelete<TService> 语法错误
- 修复 PcAuthService.cs 中 const prefix 位置错乱导致编译失败的问题
- 扫描结果:缺失项 0
- 构建结果:4/4 项目编译通过
This commit is contained in:
2026-05-18 11:35:13 +08:00
parent 446502b0e9
commit fc6f9f6bc3
43 changed files with 884 additions and 233 deletions
@@ -10,9 +10,13 @@ namespace Avalonia_Services.Core
/// </summary>
public sealed class GlobalExceptionFilter : IEndpointFilter
{
/// <summary>
/// 是否在错误响应中包含异常详情。
/// </summary>
private readonly bool _includeDetails;
/// <summary>
/// 初始化全局异常过滤器。
/// </summary>
/// <param name="includeDetails">是否在响应中包含异常详情(开发环境建议 true,生产环境 false</param>
public GlobalExceptionFilter(bool includeDetails = false)
@@ -20,6 +24,11 @@ namespace Avalonia_Services.Core
_includeDetails = includeDetails;
}
/// <summary>
/// 执行过滤器逻辑:包裹下一个委托,捕获所有未处理异常并转换为统一错误响应。
/// </summary>
/// <param name="context">请求上下文。</param>
/// <param name="next">管道中的下一个委托。</param>
public async Task InvokeAsync(ServiceEndpointContext context, EndpointFilterDelegate next)
{
try
@@ -73,6 +82,11 @@ namespace Avalonia_Services.Core
}
}
/// <summary>
/// 记录异常日志,优先使用 Serilog,不可用时回退到 Console。
/// </summary>
/// <param name="context">请求上下文。</param>
/// <param name="ex">异常对象。</param>
private static void LogException(ServiceEndpointContext context, Exception ex)
{
try
+1 -1
View File
@@ -23,13 +23,13 @@ namespace Avalonia_Services.Core
/// </summary>
public sealed class AnonymousAuthService : IAuthService
{
/// <inheritdoc />
public Task<ClaimsPrincipal?> AuthenticateAsync(ServiceEndpointContext context)
{
// 匿名用户,始终通过
var identity = new ClaimsIdentity("anonymous");
return Task.FromResult<ClaimsPrincipal?>(new ClaimsPrincipal(identity));
}
/// <inheritdoc />
public Task<bool> AuthorizeAsync(ClaimsPrincipal user, string policy)
{
@@ -25,13 +25,21 @@ namespace Avalonia_Services.Core
/// </summary>
internal sealed class AnonymousEndpointFilter : IEndpointFilter
{
/// <summary>
/// 匿名过滤器的委托实现。
/// </summary>
private readonly Func<ServiceEndpointContext, EndpointFilterDelegate, Task> _filter;
/// <summary>
/// 使用匿名函数创建过滤器。
/// </summary>
/// <param name="filter">过滤器委托。</param>
public AnonymousEndpointFilter(Func<ServiceEndpointContext, EndpointFilterDelegate, Task> filter)
{
_filter = filter;
}
/// <inheritdoc />
public Task InvokeAsync(ServiceEndpointContext context, EndpointFilterDelegate next)
{
return _filter(context, next);
@@ -5,11 +5,17 @@ using Microsoft.Extensions.DependencyInjection;
namespace Avalonia_Services.Core
{
/// <summary>
/// 端点挂载的宿主目标。
/// </summary>
[Flags]
public enum EndpointHostTarget
{
/// <summary>挂载到 Avalonia-APIASP.NET Core Web API)。</summary>
Api = 1,
/// <summary>挂载到 Avalonia-PC(桌面 WebView)。</summary>
Pc = 2,
/// <summary>同时挂载到 API 和 PC。</summary>
All = Api | Pc,
}
@@ -69,6 +75,15 @@ namespace Avalonia_Services.Core
return this;
}
/// <summary>
/// 设置端点的 OpenAPI 元数据(标签、摘要、描述、请求/响应类型)。
/// </summary>
/// <param name="tag">OpenAPI 分组标签。</param>
/// <param name="summary">简要摘要。</param>
/// <param name="description">详细描述。</param>
/// <param name="requestType">请求体类型。</param>
/// <param name="responseType">成功响应类型。</param>
/// <returns>当前端点实例(Fluent API)。</returns>
public ServiceEndpoint WithOpenApi(
string tag,
string summary,
@@ -122,6 +137,11 @@ namespace Avalonia_Services.Core
return this;
}
/// <summary>
/// 判断端点是否支持指定的宿主目标。
/// </summary>
/// <param name="host">要检查的宿主目标。</param>
/// <returns>是否支持。</returns>
public bool SupportsHost(EndpointHostTarget host)
{
return (HostTarget & host) != 0;
@@ -136,6 +156,11 @@ namespace Avalonia_Services.Core
/// <summary>所有已注册的端点</summary>
public List<ServiceEndpoint> Endpoints { get; } = new();
/// <summary>
/// 获取指定宿主目标的所有端点。
/// </summary>
/// <param name="host">宿主目标。</param>
/// <returns>匹配的端点集合。</returns>
public IEnumerable<ServiceEndpoint> ForHost(EndpointHostTarget host)
{
return Endpoints.Where(endpoint => endpoint.SupportsHost(host));
@@ -152,6 +177,13 @@ namespace Avalonia_Services.Core
return AddEndpoint(pattern, "GET", handler);
}
/// <summary>
/// 注册一个带服务依赖注入的 GET 端点。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <param name="pattern">路由路径。</param>
/// <param name="handler">接受服务实例和上下文的处理器。</param>
/// <returns>已注册的端点实例。</returns>
public ServiceEndpoint MapGet<TService>(
string pattern,
Func<TService, ServiceEndpointContext, Task<object?>> handler)
@@ -168,6 +200,13 @@ namespace Avalonia_Services.Core
return AddEndpoint(pattern, "POST", handler);
}
/// <summary>
/// 注册一个带服务依赖注入的 POST 端点。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <param name="pattern">路由路径。</param>
/// <param name="handler">接受服务实例和上下文的处理器。</param>
/// <returns>已注册的端点实例。</returns>
public ServiceEndpoint MapPost<TService>(
string pattern,
Func<TService, ServiceEndpointContext, Task<object?>> handler)
@@ -184,6 +223,13 @@ namespace Avalonia_Services.Core
return AddEndpoint(pattern, "PUT", handler);
}
/// <summary>
/// 注册一个带服务依赖注入的 PUT 端点。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <param name="pattern">路由路径。</param>
/// <param name="handler">接受服务实例和上下文的处理器。</param>
/// <returns>已注册的端点实例。</returns>
public ServiceEndpoint MapPut<TService>(
string pattern,
Func<TService, ServiceEndpointContext, Task<object?>> handler)
@@ -200,6 +246,13 @@ namespace Avalonia_Services.Core
return AddEndpoint(pattern, "DELETE", handler);
}
/// <summary>
/// 注册一个带服务依赖注入的 DELETE 端点。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <param name="pattern">路由路径。</param>
/// <param name="handler">接受服务实例和上下文的处理器。</param>
/// <returns>已注册的端点实例。</returns>
public ServiceEndpoint MapDelete<TService>(
string pattern,
Func<TService, ServiceEndpointContext, Task<object?>> handler)
@@ -226,6 +279,13 @@ namespace Avalonia_Services.Core
return this;
}
/// <summary>
/// 内部方法,创建端点并添加到集合。
/// </summary>
/// <param name="pattern">路由路径。</param>
/// <param name="method">HTTP 方法。</param>
/// <param name="handler">端点处理器。</param>
/// <returns>已创建的端点实例。</returns>
private ServiceEndpoint AddEndpoint(string pattern, string method, Func<ServiceEndpointContext, Task<object?>> handler)
{
var endpoint = new ServiceEndpoint
@@ -238,6 +298,12 @@ namespace Avalonia_Services.Core
return endpoint;
}
/// <summary>
/// 创建自动从 DI 解析服务实例并调用处理器的委托包装。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <param name="handler">接受服务实例和上下文的处理器。</param>
/// <returns>包装后的处理器委托。</returns>
private static Func<ServiceEndpointContext, Task<object?>> CreateServiceHandler<TService>(
Func<TService, ServiceEndpointContext, Task<object?>> handler)
where TService : notnull
@@ -89,6 +89,11 @@ namespace Avalonia_Services.Endpoints
return ResponseHelper.Ok(forecasts, "获取天气预报成功(内存生成)");
}
/// <summary>
/// 从数据库获取用户信息(演示数据库查询),若无数据则返回演示用户。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>用户信息。</returns>
private static async Task<object?> GetUserFromDatabaseAsync(ServiceEndpointContext ctx)
{
var sp = ctx.Items["ServiceProvider"] as IServiceProvider;
@@ -109,6 +114,11 @@ namespace Avalonia_Services.Endpoints
return ResponseHelper.Ok(user);
}
/// <summary>
/// 处理前端发送的数据(POST 演示),将数据存入数据库或转为大写返回。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>处理结果。</returns>
private static async Task<object?> ProcessDataAsync(ServiceEndpointContext ctx)
{
var sp = ctx.Items["ServiceProvider"] as IServiceProvider;
@@ -8,6 +8,10 @@ namespace Avalonia_Services.Endpoints
/// </summary>
public static class AuthEndpoints
{
/// <summary>
/// 配置 API 端鉴权端点(登录、刷新、登出)。
/// </summary>
/// <param name="builder">端点构建器。</param>
public static void ConfigureApi(ServiceEndpointBuilder builder)
{
builder.ConfigureEndpoints(endpoints =>
@@ -29,6 +33,10 @@ namespace Avalonia_Services.Endpoints
});
}
/// <summary>
/// 配置 PC 端鉴权端点(授权码登录、刷新、登出)。
/// </summary>
/// <param name="builder">端点构建器。</param>
public static void ConfigurePc(ServiceEndpointBuilder builder)
{
builder.ConfigureEndpoints(endpoints =>
@@ -8,8 +8,17 @@ namespace Avalonia_Services.Extensions
/// </summary>
public class DesktopEndpointAdapter
{
/// <summary>
/// 统一端点集合。
/// </summary>
private readonly ServiceEndpointCollection _endpoints;
/// <summary>
/// 鉴权服务。
/// </summary>
private readonly IAuthService _authService;
/// <summary>
/// DI 服务提供程序。
/// </summary>
private readonly IServiceProvider _serviceProvider;
/// <summary>
@@ -17,12 +26,33 @@ namespace Avalonia_Services.Extensions
/// </summary>
public class RouteResult
{
/// <summary>
/// 获取是否匹配到路由。
/// </summary>
public bool IsMatched { get; init; }
/// <summary>
/// 获取 HTTP 状态码。
/// </summary>
public int StatusCode { get; init; } = 200;
public string StatusMessage { get; init; } = "OK";
/// <summary>
/// 获取状态描述文本。
/// </summary>
public string StatusMessage { get; init; } = "";
/// <summary>
/// 获取响应数据。
/// </summary>
public object? Data { get; init; }
/// <summary>
/// 获取响应头字典。
/// </summary>
public Dictionary<string, string> ResponseHeaders { get; init; } = new();
/// <summary>
/// 创建成功响应结果。
/// </summary>
/// <param name="data">响应数据。</param>
/// <param name="ctx">端点上下文。</param>
/// <returns>路由结果。</returns>
public static RouteResult Success(object? data, ServiceEndpointContext ctx)
{
return new RouteResult
@@ -35,6 +65,10 @@ namespace Avalonia_Services.Extensions
};
}
/// <summary>
/// 创建 404 未找到响应。
/// </summary>
/// <returns>表示未匹配的路由结果。</returns>
public static RouteResult NotFound() => new()
{
IsMatched = false,
@@ -43,6 +77,12 @@ namespace Avalonia_Services.Extensions
};
}
/// <summary>
/// 初始化桌面端点适配器。
/// </summary>
/// <param name="endpoints">端点集合。</param>
/// <param name="authService">鉴权服务。</param>
/// <param name="serviceProvider">DI 服务提供程序。</param>
public DesktopEndpointAdapter(
ServiceEndpointCollection endpoints,
IAuthService authService,
@@ -1,11 +1,33 @@
namespace Avalonia_Services.Services.AuthService
{
/// <summary>
/// API 登录请求。
/// </summary>
/// <param name="Account">账号(邮箱或用户名)。</param>
/// <param name="Password">密码。</param>
/// <param name="Roles">请求的角色列表。</param>
public sealed record ApiLoginRequest(string? Account, string? Password, string[]? Roles = null);
/// <summary>
/// API Refresh Token 请求。
/// </summary>
/// <param name="RefreshToken">刷新令牌。</param>
public sealed record ApiRefreshTokenRequest(string? RefreshToken);
/// <summary>
/// API 登出请求。
/// </summary>
/// <param name="RefreshToken">要撤销的刷新令牌。</param>
public sealed record ApiLogoutRequest(string? RefreshToken);
/// <summary>
/// 认证 Token 响应,包含 Access Token 和 Refresh Token 及其过期时间。
/// </summary>
/// <param name="AccessToken">访问令牌。</param>
/// <param name="RefreshToken">刷新令牌。</param>
/// <param name="AccessTokenExpiresAt">访问令牌过期时间。</param>
/// <param name="RefreshTokenExpiresAt">刷新令牌过期时间。</param>
/// <param name="Roles">用户角色列表。</param>
public sealed record AuthTokenResponse(
string AccessToken,
string RefreshToken,
@@ -13,25 +35,64 @@ namespace Avalonia_Services.Services.AuthService
DateTime RefreshTokenExpiresAt,
string[] Roles);
/// <summary>
/// PC 端授权码登录请求。
/// </summary>
/// <param name="AuthorizationCode">第三方授权码。</param>
public sealed record PcAuthorizeRequest(string? AuthorizationCode);
/// <summary>
/// PC 端 Token 刷新请求。
/// </summary>
/// <param name="Token">当前 Token。</param>
public sealed record PcRefreshRequest(string? Token);
/// <summary>
/// PC 端登出请求。
/// </summary>
/// <param name="Token">要清除的 Token。</param>
public sealed record PcLogoutRequest(string? Token);
/// <summary>
/// PC 端 Token 响应。
/// </summary>
/// <param name="Token">访问令牌。</param>
/// <param name="ExpiresAt">过期时间。</param>
/// <param name="Roles">用户角色列表。</param>
public sealed record PcTokenResponse(string Token, DateTime ExpiresAt, string[] Roles);
/// <summary>
/// 第三方授权检查结果。
/// </summary>
public enum ThirdPartyAuthCheckResult
{
/// <summary>授权有效。</summary>
Valid,
/// <summary>授权已丢失。</summary>
AuthorizationLost,
/// <summary>暂时性失败。</summary>
TemporaryFailure,
}
/// <summary>
/// 第三方授权客户端接口,用于验证和刷新第三方授权。
/// </summary>
public interface IPcThirdPartyAuthorizationClient
{
/// <summary>
/// 验证第三方授权码是否有效。
/// </summary>
/// <param name="authorizationCode">第三方授权码。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>授权检查结果。</returns>
Task<ThirdPartyAuthCheckResult> ValidateAuthorizationCodeAsync(string authorizationCode, CancellationToken cancellationToken = default);
/// <summary>
/// 刷新第三方授权。
/// </summary>
/// <param name="authorizationReference">授权引用标识。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>授权检查结果。</returns>
Task<ThirdPartyAuthCheckResult> RefreshAuthorizationAsync(string authorizationReference, CancellationToken cancellationToken = default);
}
}
@@ -3,21 +3,57 @@ using System.Threading.Tasks;
namespace Avalonia_Services.Services.AuthService
{
/// <summary>
/// API 鉴权端点服务接口,定义登录、刷新 Token 和登出操作。
/// </summary>
public interface IApiAuthEndpointService
{
/// <summary>
/// 处理用户登录请求。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>包含 Token 的认证响应。</returns>
Task<object?> LoginAsync(ServiceEndpointContext ctx);
/// <summary>
/// 使用 Refresh Token 刷新 Access Token。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>新的 Token 对。</returns>
Task<object?> RefreshAsync(ServiceEndpointContext ctx);
/// <summary>
/// 处理用户登出请求。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>登出结果。</returns>
Task<object?> LogoutAsync(ServiceEndpointContext ctx);
}
/// <summary>
/// PC 端鉴权端点服务接口,定义授权码登录、Token 刷新和登出操作。
/// </summary>
public interface IPcAuthEndpointService
{
/// <summary>
/// 使用授权码进行登录授权。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>包含 Token 的认证响应。</returns>
Task<object?> AuthorizeAsync(ServiceEndpointContext ctx);
/// <summary>
/// 刷新当前 Token。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>新的 Token 响应。</returns>
Task<object?> RefreshAsync(ServiceEndpointContext ctx);
/// <summary>
/// 处理用户登出请求。
/// </summary>
/// <param name="ctx">服务端点上下文。</param>
/// <returns>登出结果。</returns>
Task<object?> LogoutAsync(ServiceEndpointContext ctx);
}
}
@@ -2,6 +2,9 @@ using Avalonia_EFCore.Models;
namespace Avalonia_Services.Services
{
/// <summary>
/// 天气预报服务,随机生成未来 5 天的天气预报数据。
/// </summary>
public class WeatherForecastService
{
private static readonly string[] Summaries =
@@ -9,6 +12,10 @@ namespace Avalonia_Services.Services
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
];
/// <summary>
/// 生成未来 5 天的随机天气预报数据。
/// </summary>
/// <returns>天气预报数据集合。</returns>
public IEnumerable<WeatherForecast> GetWeatherForecasts()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast