using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; namespace Avalonia_Services.Core { /// /// 端点挂载的宿主目标。 /// [Flags] public enum EndpointHostTarget { /// 挂载到 Avalonia-API(ASP.NET Core Web API)。 Api = 1, /// 挂载到 Avalonia-PC(桌面 WebView)。 Pc = 2, /// 同时挂载到 API 和 PC。 All = Api | Pc, } /// /// 单个端点定义。 /// public class ServiceEndpoint { /// 路由路径,如 "api/wData" public string Pattern { get; init; } = string.Empty; /// HTTP 方法(GET/POST/PUT/DELETE) public string HttpMethod { get; init; } = "GET"; /// 端点名称(用于 OpenAPI / 日志) public string? Name { get; set; } /// OpenAPI 分组标签。 public string? OpenApiTag { get; set; } /// OpenAPI 摘要。 public string? OpenApiSummary { get; set; } /// OpenAPI 描述。 public string? OpenApiDescription { get; set; } /// OpenAPI 请求体类型。 public Type? OpenApiRequestType { get; set; } /// OpenAPI 200 响应数据类型。 public Type? OpenApiResponseType { get; set; } /// 端点处理器 public Func> Handler { get; init; } = _ => Task.FromResult(null); /// 该端点专属的过滤器(按顺序执行) public List Filters { get; init; } = new(); /// 是否需要鉴权 public bool RequireAuthorization { get; set; } /// 鉴权策略名 public string? Policy { get; set; } /// 允许访问该端点的角色。多个角色满足任意一个即可。 public List Roles { get; } = new(); /// 端点挂载的宿主。默认 API 和 PC 都挂载。 public EndpointHostTarget HostTarget { get; set; } = EndpointHostTarget.All; /// /// 设置端点名称(Fluent API)。 /// public ServiceEndpoint WithName(string name) { Name = name; return this; } /// /// 设置端点的 OpenAPI 元数据(标签、摘要、描述、请求/响应类型)。 /// /// OpenAPI 分组标签。 /// 简要摘要。 /// 详细描述。 /// 请求体类型。 /// 成功响应类型。 /// 当前端点实例(Fluent API)。 public ServiceEndpoint WithOpenApi( string tag, string summary, string? description = null, Type? requestType = null, Type? responseType = null) { OpenApiTag = tag; OpenApiSummary = summary; OpenApiDescription = description; OpenApiRequestType = requestType; OpenApiResponseType = responseType; return this; } /// /// 标记端点需要登录。 /// public ServiceEndpoint RequireAuth() { RequireAuthorization = true; return this; } /// /// 标记端点需要指定角色。多个角色满足任意一个即可。 /// public ServiceEndpoint RequireRoles(params string[] roles) { RequireAuthorization = true; Roles.Clear(); Roles.AddRange(roles.Where(role => !string.IsNullOrWhiteSpace(role)).Select(role => role.Trim())); return this; } /// /// 只挂载到 Avalonia-API。 /// public ServiceEndpoint ApiOnly() { HostTarget = EndpointHostTarget.Api; return this; } /// /// 只挂载到 Avalonia-PC。 /// public ServiceEndpoint PcOnly() { HostTarget = EndpointHostTarget.Pc; return this; } /// /// 判断端点是否支持指定的宿主目标。 /// /// 要检查的宿主目标。 /// 是否支持。 public bool SupportsHost(EndpointHostTarget host) { return (HostTarget & host) != 0; } } /// /// 端点集合 —— 所有端点的注册中心。在 Avalonia-Services 中统一配置。 /// public class ServiceEndpointCollection { /// 所有已注册的端点 public List Endpoints { get; } = new(); /// /// 获取指定宿主目标的所有端点。 /// /// 宿主目标。 /// 匹配的端点集合。 public IEnumerable ForHost(EndpointHostTarget host) { return Endpoints.Where(endpoint => endpoint.SupportsHost(host)); } /// 作用于所有端点的全局过滤器 public List GlobalFilters { get; } = new(); /// /// 注册一个端点。 /// public ServiceEndpoint MapGet(string pattern, Func> handler) { return AddEndpoint(pattern, "GET", handler); } /// /// 注册一个带服务依赖注入的 GET 端点。 /// /// 服务类型。 /// 路由路径。 /// 接受服务实例和上下文的处理器。 /// 已注册的端点实例。 public ServiceEndpoint MapGet( string pattern, Func> handler) where TService : notnull { return MapGet(pattern, CreateServiceHandler(handler)); } /// /// 注册一个 POST 端点。 /// public ServiceEndpoint MapPost(string pattern, Func> handler) { return AddEndpoint(pattern, "POST", handler); } /// /// 注册一个带服务依赖注入的 POST 端点。 /// /// 服务类型。 /// 路由路径。 /// 接受服务实例和上下文的处理器。 /// 已注册的端点实例。 public ServiceEndpoint MapPost( string pattern, Func> handler) where TService : notnull { return MapPost(pattern, CreateServiceHandler(handler)); } /// /// 注册一个 PUT 端点。 /// public ServiceEndpoint MapPut(string pattern, Func> handler) { return AddEndpoint(pattern, "PUT", handler); } /// /// 注册一个带服务依赖注入的 PUT 端点。 /// /// 服务类型。 /// 路由路径。 /// 接受服务实例和上下文的处理器。 /// 已注册的端点实例。 public ServiceEndpoint MapPut( string pattern, Func> handler) where TService : notnull { return MapPut(pattern, CreateServiceHandler(handler)); } /// /// 注册一个 DELETE 端点。 /// public ServiceEndpoint MapDelete(string pattern, Func> handler) { return AddEndpoint(pattern, "DELETE", handler); } /// /// 注册一个带服务依赖注入的 DELETE 端点。 /// /// 服务类型。 /// 路由路径。 /// 接受服务实例和上下文的处理器。 /// 已注册的端点实例。 public ServiceEndpoint MapDelete( string pattern, Func> handler) where TService : notnull { return MapDelete(pattern, CreateServiceHandler(handler)); } /// /// 添加全局过滤器(作用于所有端点)。 /// public ServiceEndpointCollection AddGlobalFilter(IEndpointFilter filter) { GlobalFilters.Add(filter); return this; } /// /// 通过匿名函数添加全局过滤器。 /// public ServiceEndpointCollection AddGlobalFilter(Func filter) { GlobalFilters.Add(new AnonymousEndpointFilter(filter)); return this; } /// /// 内部方法,创建端点并添加到集合。 /// /// 路由路径。 /// HTTP 方法。 /// 端点处理器。 /// 已创建的端点实例。 private ServiceEndpoint AddEndpoint(string pattern, string method, Func> handler) { var endpoint = new ServiceEndpoint { Pattern = pattern, HttpMethod = method, Handler = handler, }; Endpoints.Add(endpoint); return endpoint; } /// /// 创建自动从 DI 解析服务实例并调用处理器的委托包装。 /// /// 服务类型。 /// 接受服务实例和上下文的处理器。 /// 包装后的处理器委托。 private static Func> CreateServiceHandler( Func> handler) where TService : notnull { return async ctx => { var serviceProvider = ctx.Items["ServiceProvider"] as IServiceProvider ?? throw new InvalidOperationException("ServiceProvider 未注入。"); await using var scope = serviceProvider.CreateAsyncScope(); var service = scope.ServiceProvider.GetRequiredService(); return await handler(service, ctx); }; } } /// /// 构建器 —— 提供 Fluent API 来配置所有端点。 /// public class ServiceEndpointBuilder { /// /// 端点集合 /// public ServiceEndpointCollection Endpoints { get; } = new(); /// /// 鉴权服务(默认匿名) /// public IAuthService AuthService { get; set; } = new AnonymousAuthService(); /// /// 配置端点(在此方法中调用 endpoints.MapGet 等)。 /// public ServiceEndpointBuilder ConfigureEndpoints(Action configure) { configure(Endpoints); return this; } /// /// 设置鉴权服务。 /// public ServiceEndpointBuilder UseAuthService(IAuthService authService) { AuthService = authService; return this; } /// /// 构建最终的端点集合。 /// public ServiceEndpointCollection Build() { return Endpoints; } } }