XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.ServerInteractive

[DLL] Server interaction extension, including user identity verification and querying in conjunction with AutoConfig

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFEExtension.NetCore.ServerInteractive

Add Request/Response attributes and ClientRequestGenerator for StandardRequestServiceBase

- Add RequestAttribute and ResponseAttribute in Attributes/ - Remove PostRequest() and AnalyzeResponse() from IStandardRequestService - Add RequestPoints and ResponsePoints dictionaries to IStandardRequestService - Update StandardRequestServiceBase to partial class with virtual dictionaries - Add ClientRequestGenerator source generator (similar to EntryPointGenerator) - Add ClientRequestMethodCandidate model - Update XFEClientRequester to use dictionary-based routing - Update LoginRequestService, ReloginRequestService, GetLogRequestService, ClearLogRequestService to use [Request]/[Response] attributes - Register new diagnostic rules XFE0007-XFE0010 Agent-Logs-Url: https://github.com/XFEstudio/XFEExtension.NetCore.ServerInteractive/sessions/436def84-338f-4a12-8e86-51ed7035c2e6 Co-authored-by: XFEstudio <132526994+XFEstudio@users.noreply.github.com>

e95fa46
copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
提交于

代码差异

12 个文件 +471 -38
Modified XFEExtension.NetCore.ServerInteractive.SourceGenerator/AnalyzerReleases.Unshipped.md +5 -1
@@ -8,4 +8,8 @@ Rule ID | Category | Severity | Notes
8 8 XFE0003 | XFEServerInteractive | Error | EntryPointGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0003)
9 9 XFE0004 | XFEServerInteractive | Error | EntryPointGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0004)
10 10 XFE0005 | XFEServerInteractive | Error | EntryPointGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0005)
11 XFE0006 | XFEServerInteractive | Error | EntryPointGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0006)
11 XFE0006 | XFEServerInteractive | Error | EntryPointGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0006)
12 XFE0007 | XFEServerInteractive | Error | ClientRequestGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0007)
13 XFE0008 | XFEServerInteractive | Error | ClientRequestGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0008)
14 XFE0009 | XFEServerInteractive | Error | ClientRequestGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0009)
15 XFE0010 | XFEServerInteractive | Error | ClientRequestGenerator, [Documentation](https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0010)
Added XFEExtension.NetCore.ServerInteractive.SourceGenerator/ClientRequestGenerator.cs +316 -0
@@ -0,0 +1,316 @@
1 using Microsoft.CodeAnalysis;
2 using Microsoft.CodeAnalysis.CSharp;
3 using Microsoft.CodeAnalysis.CSharp.Syntax;
4 using Microsoft.CodeAnalysis.Text;
5 using System.Collections.Generic;
6 using System.Collections.Immutable;
7 using System.Linq;
8 using System.Text;
9 using XFEExtension.NetCore.ServerInteractive.SourceGenerator.Models;
10
11 namespace XFEExtension.NetCore.ServerInteractive.SourceGenerator;
12
13 /// <summary>
14 /// 客户端请求增量生成器
15 /// 用于自动生成StandardRequestServiceBase的请求/响应字典
16 /// </summary>
17 [Generator]
18 public class ClientRequestGenerator : IIncrementalGenerator
19 {
20 private static readonly DiagnosticDescriptor NonPartialClassRule = new(
21 id: "XFE0007",
22 title: "包含Request或Response方法的类必须为partial",
23 messageFormat: "类'{0}'必须声明为partial以便增量生成器可以生成请求/响应代码",
24 category: "XFEServerInteractive",
25 defaultSeverity: DiagnosticSeverity.Error,
26 helpLinkUri: "https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0007",
27 isEnabledByDefault: true);
28
29 private static readonly DiagnosticDescriptor MethodMustBeParameterlessRule = new(
30 id: "XFE0008",
31 title: "Request/Response方法不能有参数",
32 messageFormat: "方法'{0}'标记了[{1}]但包含参数,请求/响应方法必须是无参数的",
33 category: "XFEServerInteractive",
34 defaultSeverity: DiagnosticSeverity.Error,
35 helpLinkUri: "https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0008",
36 isEnabledByDefault: true);
37
38 private static readonly DiagnosticDescriptor InvalidReturnTypeRule = new(
39 id: "XFE0009",
40 title: "Request/Response方法返回类型无效",
41 messageFormat: "方法'{0}'的返回类型'{1}'无效,请求/响应方法必须返回object",
42 category: "XFEServerInteractive",
43 defaultSeverity: DiagnosticSeverity.Error,
44 helpLinkUri: "https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0009",
45 isEnabledByDefault: true);
46
47 private static readonly DiagnosticDescriptor InvalidPathCharactersRule = new(
48 id: "XFE0010",
49 title: "Request/Response路径包含无效字符",
50 messageFormat: "路径'{0}'包含无效字符(引号或反斜杠),这些字符不允许在路径中使用",
51 category: "XFEServerInteractive",
52 defaultSeverity: DiagnosticSeverity.Error,
53 helpLinkUri: "https://docs.xfegzs.com/View/Errors%2FServerInteractive%2FXFE0010",
54 isEnabledByDefault: true);
55
56 public void Initialize(IncrementalGeneratorInitializationContext context)
57 {
58 // 找到所有标记了RequestAttribute或ResponseAttribute的方法
59 var methodDeclarations = context.SyntaxProvider
60 .CreateSyntaxProvider(
61 predicate: static (s, _) => IsCandidateMethod(s),
62 transform: static (ctx, _) => GetMethodForGeneration(ctx))
63 .Where(static m => m is not null);
64
65 // 按类分组
66 var compilationAndMethods = context.CompilationProvider.Combine(methodDeclarations.Collect());
67
68 // 生成源代码
69 context.RegisterSourceOutput(compilationAndMethods,
70 static (spc, source) => Execute(source.Left, source.Right, spc));
71 }
72
73 private static bool IsCandidateMethod(SyntaxNode node) => node is MethodDeclarationSyntax { AttributeLists.Count: > 0 };
74
75 private static ClientRequestMethodCandidate? GetMethodForGeneration(GeneratorSyntaxContext context)
76 {
77 var methodDeclaration = (MethodDeclarationSyntax)context.Node;
78 var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration);
79
80 if (methodSymbol is null)
81 return null;
82
83 // 检查是否有RequestAttribute或ResponseAttribute
84 var requestAttribute = methodSymbol.GetAttributes()
85 .FirstOrDefault(a => a.AttributeClass?.Name == "RequestAttribute");
86 var responseAttribute = methodSymbol.GetAttributes()
87 .FirstOrDefault(a => a.AttributeClass?.Name == "ResponseAttribute");
88
89 if (requestAttribute is null && responseAttribute is null)
90 return null;
91
92 var isRequest = requestAttribute is not null;
93 var attribute = isRequest ? requestAttribute! : responseAttribute!;
94 var attributeName = isRequest ? "Request" : "Response";
95
96 // 获取Path参数
97 var path = attribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
98 if (string.IsNullOrEmpty(path))
99 return null;
100
101 // 检查返回类型:必须为object
102 var returnType = methodSymbol.ReturnType;
103 var isObjectReturn = returnType.SpecialType == SpecialType.System_Object;
104
105 // 检查包含类型是否为partial
106 var classDeclaration = methodDeclaration.Parent as ClassDeclarationSyntax;
107 var isContainingTypePartial = classDeclaration?.Modifiers.Any(SyntaxKind.PartialKeyword) ?? false;
108
109 // 获取泛型类型参数和约束
110 var typeParameters = classDeclaration?.TypeParameterList?.ToString().Trim() ?? "";
111 var typeConstraints = classDeclaration?.ConstraintClauses.ToString().Trim() ?? "";
112
113 var containingType = methodSymbol.ContainingType;
114
115 // 获取位置信息
116 var methodLocation = LocationInfo.From(methodDeclaration.GetLocation());
117 var classLocation = classDeclaration is not null
118 ? LocationInfo.From(classDeclaration.Identifier.GetLocation())
119 : methodLocation;
120
121 // 收集源文件的using指令
122 var compilationUnit = methodDeclaration.SyntaxTree.GetRoot() as CompilationUnitSyntax;
123 var usingDirectives = compilationUnit?.Usings
124 .Select(u => u.ToString().Trim())
125 .ToArray() ?? new string[0];
126
127 return new ClientRequestMethodCandidate(
128 containingType.ContainingNamespace.ToDisplayString(),
129 containingType.Name,
130 methodSymbol.Name,
131 path!,
132 isRequest,
133 isContainingTypePartial,
134 methodSymbol.Parameters.Length,
135 isObjectReturn,
136 returnType.ToDisplayString(),
137 methodLocation,
138 classLocation,
139 typeParameters,
140 typeConstraints,
141 attributeName,
142 usingDirectives);
143 }
144
145 private static void Execute(Compilation compilation, ImmutableArray<ClientRequestMethodCandidate?> methods, SourceProductionContext context)
146 {
147 if (methods.IsDefaultOrEmpty)
148 return;
149
150 var validMethods = new List<ClientRequestMethodCandidate>();
151
152 // 校验并报告诊断信息
153 foreach (var method in methods)
154 {
155 if (method is null) continue;
156
157 var isValid = true;
158
159 // 校验:包含类型必须为partial
160 if (!method.IsContainingTypePartial)
161 {
162 context.ReportDiagnostic(Diagnostic.Create(
163 NonPartialClassRule,
164 method.ClassLocation.ToLocation(),
165 method.ClassName));
166 isValid = false;
167 }
168
169 // 校验:方法不能有参数
170 if (method.ParameterCount > 0)
171 {
172 context.ReportDiagnostic(Diagnostic.Create(
173 MethodMustBeParameterlessRule,
174 method.MethodLocation.ToLocation(),
175 method.MethodName,
176 method.AttributeName));
177 isValid = false;
178 }
179
180 // 校验:返回类型必须为object
181 if (!method.HasValidReturnType)
182 {
183 context.ReportDiagnostic(Diagnostic.Create(
184 InvalidReturnTypeRule,
185 method.MethodLocation.ToLocation(),
186 method.MethodName,
187 method.ReturnTypeName));
188 isValid = false;
189 }
190
191 // 校验:路径不能包含引号或反斜杠
192 if (method.Path.Contains("\"") || method.Path.Contains("\\"))
193 {
194 context.ReportDiagnostic(Diagnostic.Create(
195 InvalidPathCharactersRule,
196 method.MethodLocation.ToLocation(),
197 method.Path));
198 isValid = false;
199 }
200
201 if (isValid)
202 {
203 validMethods.Add(method);
204 }
205 }
206
207 if (validMethods.Count == 0)
208 return;
209
210 // 按类分组并生成代码
211 var methodsByClass = validMethods.GroupBy(m => (m.Namespace, m.ClassName, m.TypeParameters, m.TypeConstraints));
212
213 foreach (var group in methodsByClass)
214 {
215 var (namespaceName, className, typeParameters, typeConstraints) = group.Key;
216 var methodInfos = group.ToList();
217 var constraintsSuffix = string.IsNullOrEmpty(typeConstraints) ? "" : $" {typeConstraints}";
218
219 var requestMethods = methodInfos.Where(m => m.IsRequest).ToList();
220 var responseMethods = methodInfos.Where(m => !m.IsRequest).ToList();
221
222 // 收集所有路径(去重)
223 var allPaths = methodInfos.Select(m => m.Path).Distinct().ToList();
224
225 // 收集所有using指令(合并去重)
226 var allUsings = methodInfos
227 .SelectMany(m => m.UsingDirectives)
228 .Distinct()
229 .OrderBy(u => u)
230 .ToList();
231
232 var sourceBuilder = new StringBuilder();
233 sourceBuilder.AppendLine(@"// <auto-generated/>
234 #nullable enable
235 ");
236
237 // 添加using指令
238 foreach (var usingDirective in allUsings)
239 {
240 sourceBuilder.AppendLine(usingDirective);
241 }
242
243 // 确保基础using存在
244 if (!allUsings.Any(u => u.Contains("System;") && !u.Contains("System.")))
245 sourceBuilder.AppendLine("using System;");
246 if (!allUsings.Any(u => u.Contains("System.Collections.Generic")))
247 sourceBuilder.AppendLine("using System.Collections.Generic;");
248
249 sourceBuilder.AppendLine($@"
250 namespace {namespaceName}
251 {{
252 /// <summary>
253 /// {className}的自动生成请求/响应字典部分类
254 /// </summary>
255 public partial class {className}{typeParameters}{constraintsSuffix}
256 {{
257 /// <summary>
258 /// 本类型的请求路由路径列表(覆盖基类的空列表)
259 /// </summary>
260 public new static List<string> RequestRouteList {{ get; }} = new()
261 {{");
262
263 // 添加所有路径到静态列表
264 foreach (var path in allPaths)
265 {
266 sourceBuilder.AppendLine($" \"{EscapeStringLiteral(path)}\",");
267 }
268
269 sourceBuilder.AppendLine($@" }};
270
271 private Dictionary<string, Func<object>>? _generatedRequestPoints;
272 /// <inheritdoc/>
273 public override Dictionary<string, Func<object>> RequestPoints
274 {{
275 get => _generatedRequestPoints ??= new Dictionary<string, Func<object>>()
276 {{");
277
278 // 添加请求方法
279 foreach (var method in requestMethods)
280 {
281 sourceBuilder.AppendLine($" {{ \"{EscapeStringLiteral(method.Path)}\", {method.MethodName} }},");
282 }
283
284 sourceBuilder.AppendLine($@" }};
285 }}
286
287 private Dictionary<string, Func<object>>? _generatedResponsePoints;
288 /// <inheritdoc/>
289 public override Dictionary<string, Func<object>> ResponsePoints
290 {{
291 get => _generatedResponsePoints ??= new Dictionary<string, Func<object>>()
292 {{");
293
294 // 添加响应方法
295 foreach (var method in responseMethods)
296 {
297 sourceBuilder.AppendLine($" {{ \"{EscapeStringLiteral(method.Path)}\", {method.MethodName} }},");
298 }
299
300 sourceBuilder.AppendLine(@" };
301 }
302 }
303 }");
304
305 context.AddSource($"{className}.ClientRequests.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
306 }
307 }
308
309 /// <summary>
310 /// 转义字符串字面量中的特殊字符
311 /// </summary>
312 private static string EscapeStringLiteral(string value)
313 {
314 return value.Replace("\\", "\\\\").Replace("\"", "\\\"");
315 }
316 }
Added XFEExtension.NetCore.ServerInteractive.SourceGenerator/Models/ClientRequestMethodCandidate.cs +27 -0
@@ -0,0 +1,27 @@
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace XFEExtension.NetCore.ServerInteractive.SourceGenerator.Models;
6
7 /// <summary>
8 /// 客户端请求方法候选信息,包含验证所需的所有数据
9 /// </summary>
10 public class ClientRequestMethodCandidate(string namespaceName, string className, string methodName, string path, bool isRequest, bool isContainingTypePartial, int parameterCount, bool hasValidReturnType, string returnTypeName, LocationInfo methodLocation, LocationInfo classLocation, string typeParameters, string typeConstraints, string attributeName, string[] usingDirectives)
11 {
12 public string Namespace { get; } = namespaceName;
13 public string ClassName { get; } = className;
14 public string MethodName { get; } = methodName;
15 public string Path { get; } = path;
16 public bool IsRequest { get; } = isRequest;
17 public bool IsContainingTypePartial { get; } = isContainingTypePartial;
18 public int ParameterCount { get; } = parameterCount;
19 public bool HasValidReturnType { get; } = hasValidReturnType;
20 public string ReturnTypeName { get; } = returnTypeName;
21 public LocationInfo MethodLocation { get; } = methodLocation;
22 public LocationInfo ClassLocation { get; } = classLocation;
23 public string TypeParameters { get; } = typeParameters;
24 public string TypeConstraints { get; } = typeConstraints;
25 public string AttributeName { get; } = attributeName;
26 public string[] UsingDirectives { get; } = usingDirectives;
27 }
Added XFEExtension.NetCore.ServerInteractive/Attributes/RequestAttribute.cs +22 -0
@@ -0,0 +1,22 @@
1 namespace XFEExtension.NetCore.ServerInteractive.Attributes;
2
3 /// <summary>
4 /// 请求特性,用于标记IStandardRequestService中构造请求体的方法
5 /// </summary>
6 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
7 public class RequestAttribute : Attribute
8 {
9 /// <summary>
10 /// 请求路径
11 /// </summary>
12 public string Path { get; }
13
14 /// <summary>
15 /// 创建请求特性
16 /// </summary>
17 /// <param name="path">请求路径(例如:user/login)</param>
18 public RequestAttribute(string path)
19 {
20 Path = path;
21 }
22 }
Added XFEExtension.NetCore.ServerInteractive/Attributes/ResponseAttribute.cs +22 -0
@@ -0,0 +1,22 @@
1 namespace XFEExtension.NetCore.ServerInteractive.Attributes;
2
3 /// <summary>
4 /// 响应特性,用于标记IStandardRequestService中解析响应的方法
5 /// </summary>
6 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
7 public class ResponseAttribute : Attribute
8 {
9 /// <summary>
10 /// 响应路径
11 /// </summary>
12 public string Path { get; }
13
14 /// <summary>
15 /// 创建响应特性
16 /// </summary>
17 /// <param name="path">响应路径(例如:user/login)</param>
18 public ResponseAttribute(string path)
19 {
20 Path = path;
21 }
22 }
Modified XFEExtension.NetCore.ServerInteractive/Implements/Requester/StandardRequestServiceBase.cs +8 -3
@@ -6,8 +6,13 @@ namespace XFEExtension.NetCore.ServerInteractive.Implements.Requester;
6 6 /// <summary>
7 7 /// 标准请求服务基类
8 8 /// </summary>
9 public abstract class StandardRequestServiceBase : IStandardRequestService
9 public abstract partial class StandardRequestServiceBase : IStandardRequestService
10 10 {
11 /// <summary>
12 /// 本类型的请求路由路径列表(由增量生成器自动填充)
13 /// </summary>
14 public static List<string> RequestRouteList { get; } = [];
15
11 16 /// <inheritdoc/>
12 17 public string Session { get => XFEClientRequester.Session; set => XFEClientRequester.Session = value; }
13 18 /// <inheritdoc />
@@ -24,8 +29,8 @@ public abstract class StandardRequestServiceBase : IStandardRequestService
24 29 public XFEClientRequester XFEClientRequester { get; set; }
25 30
26 31 /// <inheritdoc/>
27 public abstract object AnalyzeResponse();
32 public virtual Dictionary<string, Func<object>> RequestPoints { get; } = new();
28 33
29 34 /// <inheritdoc/>
30 public abstract object PostRequest();
35 public virtual Dictionary<string, Func<object>> ResponsePoints { get; } = new();
31 36 }
Modified XFEExtension.NetCore.ServerInteractive/Interfaces/Requester/IStandardRequestService.cs +4 -6
@@ -30,13 +30,11 @@ public interface IStandardRequestService : IRequestServiceBase
30 30 /// </summary>
31 31 object[] Parameters { get; internal set; }
32 32 /// <summary>
33 /// 提交请求体
33 /// 请求方法字典,Key为请求路径,Value为对应的构造请求体方法
34 34 /// </summary>
35 /// <returns></returns>
36 object PostRequest();
35 Dictionary<string, Func<object>> RequestPoints { get; }
37 36 /// <summary>
38 /// 接收到返回后解析
37 /// 响应方法字典,Key为请求路径,Value为对应的解析响应方法
39 38 /// </summary>
40 /// <returns></returns>
41 object AnalyzeResponse();
39 Dictionary<string, Func<object>> ResponsePoints { get; }
42 40 }
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Requester/Services/ClearLogRequestService.cs +13 -6
@@ -1,17 +1,24 @@
1 using XFEExtension.NetCore.ServerInteractive.Implements.Requester;
1 using XFEExtension.NetCore.ServerInteractive.Attributes;
2 using XFEExtension.NetCore.ServerInteractive.Implements.Requester;
2 3
3 4 namespace XFEExtension.NetCore.ServerInteractive.Utilities.Requester.Services;
4 5
5 6 /// <summary>
6 7 /// 清除日志请求服务
7 8 /// </summary>
8 public class ClearLogRequestService : StandardRequestServiceBase
9 public partial class ClearLogRequestService : StandardRequestServiceBase
9 10 {
10 /// <inheritdoc/>
11 public override object AnalyzeResponse() => true;
11 /// <summary>
12 /// 解析清除日志响应
13 /// </summary>
14 [Response("log/clear")]
15 public object AnalyzeClearLogResponse() => true;
12 16
13 /// <inheritdoc/>
14 public override object PostRequest() => new
17 /// <summary>
18 /// 构造清除日志请求体
19 /// </summary>
20 [Request("log/clear")]
21 public object PostClearLogRequest() => new
15 22 {
16 23 session = Session,
17 24 deviceInfo = DeviceInfo
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Requester/Services/GetLogRequestService.cs +13 -6
@@ -1,17 +1,24 @@
1 using XFEExtension.NetCore.ServerInteractive.Implements.Requester;
1 using XFEExtension.NetCore.ServerInteractive.Attributes;
2 using XFEExtension.NetCore.ServerInteractive.Implements.Requester;
2 3
3 4 namespace XFEExtension.NetCore.ServerInteractive.Utilities.Requester.Services;
4 5
5 6 /// <summary>
6 7 /// 获取日志请求服务
7 8 /// </summary>
8 public class GetLogRequestService : StandardRequestServiceBase
9 public partial class GetLogRequestService : StandardRequestServiceBase
9 10 {
10 /// <inheritdoc/>
11 public override object AnalyzeResponse() => Response;
11 /// <summary>
12 /// 解析获取日志响应
13 /// </summary>
14 [Response("log/get")]
15 public object AnalyzeGetLogResponse() => Response;
12 16
13 /// <inheritdoc/>
14 public override object PostRequest() => new
17 /// <summary>
18 /// 构造获取日志请求体
19 /// </summary>
20 [Request("log/get")]
21 public object PostGetLogRequest() => new
15 22 {
16 23 session = Session,
17 24 deviceInfo = DeviceInfo,
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Requester/Services/LoginRequestService.cs +12 -5
@@ -1,4 +1,5 @@
1 1 using System.Text.Json;
2 using XFEExtension.NetCore.ServerInteractive.Attributes;
2 3 using XFEExtension.NetCore.ServerInteractive.Implements.Requester;
3 4 using XFEExtension.NetCore.ServerInteractive.Interfaces;
4 5 using XFEExtension.NetCore.ServerInteractive.Models.RequesterModels;
@@ -9,7 +10,7 @@ namespace XFEExtension.NetCore.ServerInteractive.Utilities.Requester.Services;
9 10 /// <summary>
10 11 /// 登录请求服务
11 12 /// </summary>
12 public class LoginRequestService<T> : StandardRequestServiceBase where T : IUserFaceInfo
13 public partial class LoginRequestService<T> : StandardRequestServiceBase where T : IUserFaceInfo
13 14 {
14 15 private readonly JsonSerializerOptions _jsonSerializerOptions = new();
15 16
@@ -18,16 +19,22 @@ public class LoginRequestService<T> : StandardRequestServiceBase where T : IUser
18 19 /// </summary>
19 20 public LoginRequestService() => _jsonSerializerOptions.Converters.Add(new JsonDateTimeConverter());
20 21
21 /// <inheritdoc/>
22 public override object AnalyzeResponse()
22 /// <summary>
23 /// 解析登录响应
24 /// </summary>
25 [Response("user/login")]
26 public object AnalyzeLoginResponse()
23 27 {
24 28 var result = JsonSerializer.Deserialize<UserLoginResult<T>>(Response, _jsonSerializerOptions);
25 29 Session = result!.Session;
26 30 return result;
27 31 }
28 32
29 /// <inheritdoc/>
30 public override object PostRequest() => new
33 /// <summary>
34 /// 构造登录请求体
35 /// </summary>
36 [Request("user/login")]
37 public object PostLoginRequest() => new
31 38 {
32 39 deviceInfo = DeviceInfo,
33 40 account = Parameters[0],
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Requester/Services/ReloginRequestService.cs +13 -5
@@ -1,4 +1,5 @@
1 1 using System.Text.Json;
2 using XFEExtension.NetCore.ServerInteractive.Attributes;
2 3 using XFEExtension.NetCore.ServerInteractive.Implements.Requester;
3 4 using XFEExtension.NetCore.ServerInteractive.Interfaces;
4 5 using XFEExtension.NetCore.ServerInteractive.Utilities.JsonConverter;
@@ -8,7 +9,7 @@ namespace XFEExtension.NetCore.ServerInteractive.Utilities.Requester.Services;
8 9 /// <summary>
9 10 /// 登录校验请求服务
10 11 /// </summary>
11 public class ReloginRequestService<T> : StandardRequestServiceBase where T : IUserFaceInfo
12 public partial class ReloginRequestService<T> : StandardRequestServiceBase where T : IUserFaceInfo
12 13 {
13 14 private readonly JsonSerializerOptions _jsonSerializerOptions = new();
14 15
@@ -16,11 +17,18 @@ public class ReloginRequestService<T> : StandardRequestServiceBase where T : IUs
16 17 /// 登录校验请求服务
17 18 /// </summary>
18 19 public ReloginRequestService() => _jsonSerializerOptions.Converters.Add(new JsonDateTimeConverter());
19 /// <inheritdoc/>
20 public override object AnalyzeResponse() => JsonSerializer.Deserialize<T>(Response, _jsonSerializerOptions)!;
21 20
22 /// <inheritdoc/>
23 public override object PostRequest() => new
21 /// <summary>
22 /// 解析登录校验响应
23 /// </summary>
24 [Response("user/relogin")]
25 public object AnalyzeReloginResponse() => JsonSerializer.Deserialize<T>(Response, _jsonSerializerOptions)!;
26
27 /// <summary>
28 /// 构造登录校验请求体
29 /// </summary>
30 [Request("user/relogin")]
31 public object PostReloginRequest() => new
24 32 {
25 33 session = Session,
26 34 deviceInfo = DeviceInfo,
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Requester/XFEClientRequester.cs +16 -6
@@ -74,16 +74,21 @@ public abstract class XFEClientRequester : IRequesterBase
74 74 xFEService.Route = serviceName;
75 75 xFEService.DeviceInfo = DeviceInfo;
76 76 xFEService.Parameters = parameters;
77 var (response, code) = await InteractiveHelper.GetServerResponse(RequestAddress + $"/{serviceName}", xFEService.PostRequest(), _jsonSerializerOptions);
77 if (!xFEService.RequestPoints.TryGetValue(serviceName, out var requestHandler))
78 throw new XFERequesterException($"未找到路由'{serviceName}'对应的[Request]方法");
79 var (response, code) = await InteractiveHelper.GetServerResponse(RequestAddress + $"/{serviceName}", requestHandler(), _jsonSerializerOptions);
78 80 result.StatusCode = code;
79 81 if (code == HttpStatusCode.OK)
80 82 {
81 83 xFEService.Response = response;
82 84 xFEService.UnescapedResponse = Regex.Unescape(response);
83 var requestResult = xFEService.AnalyzeResponse();
85 if (xFEService.ResponsePoints.TryGetValue(serviceName, out var responseHandler))
86 {
87 var requestResult = responseHandler();
88 result.Result = requestResult;
89 }
84 90 MessageReceived?.Invoke(this, new ServerInteractiveEventArgsImpl("Success", code));
85 91 result.Message = "Success";
86 result.Result = requestResult;
87 92 }
88 93 else
89 94 {
@@ -114,16 +119,21 @@ public abstract class XFEClientRequester : IRequesterBase
114 119 instance.Route = serviceName;
115 120 instance.DeviceInfo = DeviceInfo;
116 121 instance.Parameters = parameters;
117 var (response, code) = await InteractiveHelper.GetServerResponse(RequestAddress + $"/{serviceName}", instance.PostRequest(), _jsonSerializerOptions);
122 if (!instance.RequestPoints.TryGetValue(serviceName, out var requestHandler))
123 throw new XFERequesterException($"未找到路由'{serviceName}'对应的[Request]方法");
124 var (response, code) = await InteractiveHelper.GetServerResponse(RequestAddress + $"/{serviceName}", requestHandler(), _jsonSerializerOptions);
118 125 result.StatusCode = code;
119 126 if (code == HttpStatusCode.OK)
120 127 {
121 128 instance.Response = response;
122 129 instance.UnescapedResponse = Regex.Unescape(response);
123 var requestResult = instance.AnalyzeResponse();
130 if (instance.ResponsePoints.TryGetValue(serviceName, out var responseHandler))
131 {
132 var requestResult = responseHandler();
133 result.Result = requestResult;
134 }
124 135 MessageReceived?.Invoke(this, new ServerInteractiveEventArgsImpl("Success", code));
125 136 result.Message = "Success";
126 result.Result = requestResult;
127 137 }
128 138 else
129 139 {