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

完成入口点验证系统重构:添加增量生成器和向后兼容性支持

Agent-Logs-Url: https://github.com/XFEstudio/XFEExtension.NetCore.ServerInteractive/sessions/94801386-67f0-44c8-99b7-7dbcc8a45b8e Co-authored-by: XFEstudio <132526994+XFEstudio@users.noreply.github.com>

2f7ff14
anthropic-code-agent[bot] <242468646+Claude@users.noreply.github.com>
提交于

代码差异

6 个文件 +235 -13
Added XFEExtension.NetCore.ServerInteractive.SourceGenerator/EntryPointGenerator.cs +154 -0
@@ -0,0 +1,154 @@
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
10 namespace XFEExtension.NetCore.ServerInteractive.SourceGenerator;
11
12 /// <summary>
13 /// 次级入口点增量生成器
14 /// 用于自动生成IServerCoreStandardService的入口点字典
15 /// </summary>
16 [Generator]
17 public class EntryPointGenerator : IIncrementalGenerator
18 {
19 public void Initialize(IncrementalGeneratorInitializationContext context)
20 {
21 // 找到所有标记了EntryPointAttribute的方法
22 var methodDeclarations = context.SyntaxProvider
23 .CreateSyntaxProvider(
24 predicate: static (s, _) => IsCandidateMethod(s),
25 transform: static (ctx, _) => GetMethodForGeneration(ctx))
26 .Where(static m => m is not null);
27
28 // 按类分组
29 var compilationAndMethods = context.CompilationProvider.Combine(methodDeclarations.Collect());
30
31 // 生成源代码
32 context.RegisterSourceOutput(compilationAndMethods,
33 static (spc, source) => Execute(source.Left, source.Right!, spc));
34 }
35
36 private static bool IsCandidateMethod(SyntaxNode node)
37 {
38 return node is MethodDeclarationSyntax m && m.AttributeLists.Count > 0;
39 }
40
41 private static MethodInfo? GetMethodForGeneration(GeneratorSyntaxContext context)
42 {
43 var methodDeclaration = (MethodDeclarationSyntax)context.Node;
44 var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration);
45
46 if (methodSymbol is null)
47 return null;
48
49 // 检查是否有EntryPointAttribute
50 var entryPointAttribute = methodSymbol.GetAttributes()
51 .FirstOrDefault(a => a.AttributeClass?.Name == "EntryPointAttribute");
52
53 if (entryPointAttribute is null)
54 return null;
55
56 // 获取Path参数
57 var path = entryPointAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
58 if (string.IsNullOrEmpty(path))
59 return null;
60
61 // 检查是否为异步方法
62 var isAsync = methodSymbol.IsAsync ||
63 (methodSymbol.ReturnType is INamedTypeSymbol returnType &&
64 returnType.Name == "Task");
65
66 var containingType = methodSymbol.ContainingType;
67
68 return new MethodInfo(
69 containingType.ContainingNamespace.ToDisplayString(),
70 containingType.Name,
71 methodSymbol.Name,
72 path!,
73 isAsync
74 );
75 }
76
77 private static void Execute(Compilation compilation, ImmutableArray<MethodInfo?> methods, SourceProductionContext context)
78 {
79 if (methods.IsDefaultOrEmpty)
80 return;
81
82 // 按类分组
83 var methodsByClass = methods
84 .Where(m => m is not null)
85 .GroupBy(m => (m!.Namespace, m.ClassName));
86
87 foreach (var group in methodsByClass)
88 {
89 var (namespaceName, className) = group.Key;
90 var methodInfos = group.ToList();
91
92 var sourceBuilder = new StringBuilder();
93 sourceBuilder.AppendLine($@"// <auto-generated/>
94 #nullable enable
95
96 using System;
97 using System.Collections.Generic;
98 using System.Threading.Tasks;
99
100 namespace {namespaceName}
101 {{
102 /// <summary>
103 /// {className}的自动生成入口点字典部分类
104 /// </summary>
105 public partial class {className}
106 {{
107 /// <inheritdoc/>
108 public Dictionary<string, Action> SyncEntryPoints {{ get; }} = new()
109 {{");
110
111 // 添加同步入口点
112 foreach (var method in methodInfos.Where(m => !m!.IsAsync))
113 {
114 sourceBuilder.AppendLine($" {{ \"{method!.Path}\", {method.MethodName} }},");
115 }
116
117 sourceBuilder.AppendLine($@" }};
118
119 /// <inheritdoc/>
120 public Dictionary<string, Func<Task>> AsyncEntryPoints {{ get; }} = new()
121 {{");
122
123 // 添加异步入口点
124 foreach (var method in methodInfos.Where(m => m!.IsAsync))
125 {
126 sourceBuilder.AppendLine($" {{ \"{method!.Path}\", {method.MethodName} }},");
127 }
128
129 sourceBuilder.AppendLine(@" };
130 }
131 }");
132
133 context.AddSource($"{className}.EntryPoints.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
134 }
135 }
136
137 private class MethodInfo
138 {
139 public string Namespace { get; }
140 public string ClassName { get; }
141 public string MethodName { get; }
142 public string Path { get; }
143 public bool IsAsync { get; }
144
145 public MethodInfo(string namespaceName, string className, string methodName, string path, bool isAsync)
146 {
147 Namespace = namespaceName;
148 ClassName = className;
149 MethodName = methodName;
150 Path = path;
151 IsAsync = isAsync;
152 }
153 }
154 }
Added XFEExtension.NetCore.ServerInteractive.SourceGenerator/XFEExtension.NetCore.ServerInteractive.SourceGenerator.csproj +20 -0
@@ -0,0 +1,20 @@
1 <Project Sdk="Microsoft.NET.Sdk">
2
3 <PropertyGroup>
4 <TargetFramework>netstandard2.0</TargetFramework>
5 <LangVersion>latest</LangVersion>
6 <Nullable>enable</Nullable>
7 <IsRoslynComponent>true</IsRoslynComponent>
8 <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
9 <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
10 </PropertyGroup>
11
12 <ItemGroup>
13 <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
14 <PrivateAssets>all</PrivateAssets>
15 <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16 </PackageReference>
17 <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
18 </ItemGroup>
19
20 </Project>
Modified XFEExtension.NetCore.ServerInteractive.slnx +1 -0
@@ -2,4 +2,5 @@
2 2 <Project Path="XFEExtension.NetCore.ServerInteractive.Test/XFEExtension.NetCore.ServerInteractive.Test.csproj" />
3 3 <Project Path="XFEExtension.NetCore.ServerInteractive.TServer/XFEExtension.NetCore.ServerInteractive.TServer.csproj" Id="48ae17dc-8466-413f-8e8e-cbfc6f59fbe8" />
4 4 <Project Path="XFEExtension.NetCore.ServerInteractive/XFEExtension.NetCore.ServerInteractive.csproj" />
5 <Project Path="XFEExtension.NetCore.ServerInteractive.SourceGenerator/XFEExtension.NetCore.ServerInteractive.SourceGenerator.csproj" />
5 6 </Solution>
Modified XFEExtension.NetCore.ServerInteractive/Implements/CoreService/ServerCoreStandardServiceBase.cs +19 -5
@@ -1,16 +1,30 @@
1 using XFEExtension.NetCore.ServerInteractive.Interfaces.CoreService;
1 using XFEExtension.NetCore.ServerInteractive.Interfaces.CoreService;
2 2
3 3 namespace XFEExtension.NetCore.ServerInteractive.Implements.CoreService;
4 4
5 5 /// <summary>
6 6 /// 服务器标准核心服务基类
7 7 /// </summary>
8 public abstract class ServerCoreStandardServiceBase : XFEServerCoreServiceBase, IServerCoreStandardService
8 public abstract partial class ServerCoreStandardServiceBase : XFEServerCoreServiceBase, IServerCoreStandardService
9 9 {
10 10 /// <inheritdoc/>
11 public virtual void Initialize() { }
11 public virtual Dictionary<string, Action> SyncEntryPoints { get; } = new();
12
12 13 /// <inheritdoc/>
13 public virtual void RequestReceive() { }
14 public virtual Dictionary<string, Func<Task>> AsyncEntryPoints { get; } = new();
15
14 16 /// <inheritdoc/>
17 public virtual void Initialize() { }
18
19 /// <summary>
20 /// 服务器标准请求接收事件(已废弃,请使用EntryPointAttribute特性标记方法)
21 /// </summary>
22 [Obsolete("此方法已废弃,请使用EntryPointAttribute特性标记方法来定义次级入口点")]
23 public virtual void RequestReceive() { }
24
25 /// <summary>
26 /// 服务器标准请求接收异步事件(已废弃,请使用EntryPointAttribute特性标记方法)
27 /// </summary>
28 [Obsolete("此方法已废弃,请使用EntryPointAttribute特性标记方法来定义次级入口点")]
15 29 public virtual Task RequestReceiveAsync() => Task.CompletedTask;
16 }
30 }
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Server/XFEServerCore.cs +37 -8
@@ -4,6 +4,7 @@ using XFEExtension.NetCore.AutoImplement;
4 4 using XFEExtension.NetCore.CyberComm;
5 5 using XFEExtension.NetCore.DelegateExtension;
6 6 using XFEExtension.NetCore.ServerInteractive.Exceptions;
7 using XFEExtension.NetCore.ServerInteractive.Implements.CoreService;
7 8 using XFEExtension.NetCore.ServerInteractive.Implements.ServerService;
8 9 using XFEExtension.NetCore.ServerInteractive.Interfaces.CoreService;
9 10 using XFEExtension.NetCore.ServerInteractive.Models.ServerModels;
@@ -130,13 +131,27 @@ public abstract class XFEServerCore : ServerCoreServiceBase
130 131 serviceInstance.Initialize();
131 132
132 133 // 根据次级入口点调用对应的处理方法
133 if (serviceInstance.SyncEntryPoints.TryGetValue(execute, out var syncHandler))
134 var hasSyncHandler = serviceInstance.SyncEntryPoints.TryGetValue(execute, out var syncHandler);
135 var hasAsyncHandler = serviceInstance.AsyncEntryPoints.TryGetValue(execute, out var asyncHandler);
136
137 if (hasSyncHandler || hasAsyncHandler)
134 138 {
135 syncHandler();
139 // 使用新的入口点字典系统
140 if (hasSyncHandler)
141 syncHandler!();
142 if (hasAsyncHandler)
143 await asyncHandler!();
136 144 }
137 if (serviceInstance.AsyncEntryPoints.TryGetValue(execute, out var asyncHandler))
145 else
138 146 {
139 await asyncHandler();
147 // 向后兼容:如果字典为空,使用旧的RequestReceive方法
148 if (serviceInstance is ServerCoreStandardServiceBase baseService)
149 {
150 #pragma warning disable CS0618 // 类型或成员已过时
151 baseService.RequestReceive();
152 await baseService.RequestReceiveAsync();
153 #pragma warning restore CS0618 // 类型或成员已过时
154 }
140 155 }
141 156 }
142 157 catch (Exception ex)
@@ -165,13 +180,27 @@ public abstract class XFEServerCore : ServerCoreServiceBase
165 180 instance.Initialize();
166 181
167 182 // 根据次级入口点调用对应的处理方法
168 if (instance.SyncEntryPoints.TryGetValue(execute, out var syncHandler))
183 var hasSyncHandler = instance.SyncEntryPoints.TryGetValue(execute, out var syncHandler);
184 var hasAsyncHandler = instance.AsyncEntryPoints.TryGetValue(execute, out var asyncHandler);
185
186 if (hasSyncHandler || hasAsyncHandler)
169 187 {
170 syncHandler();
188 // 使用新的入口点字典系统
189 if (hasSyncHandler)
190 syncHandler!();
191 if (hasAsyncHandler)
192 await asyncHandler!();
171 193 }
172 if (instance.AsyncEntryPoints.TryGetValue(execute, out var asyncHandler))
194 else
173 195 {
174 await asyncHandler();
196 // 向后兼容:如果字典为空,使用旧的RequestReceive方法
197 if (instance is ServerCoreStandardServiceBase baseService)
198 {
199 #pragma warning disable CS0618 // 类型或成员已过时
200 baseService.RequestReceive();
201 await baseService.RequestReceiveAsync();
202 #pragma warning restore CS0618 // 类型或成员已过时
203 }
175 204 }
176 205 }
177 206 catch (Exception ex)
Modified XFEExtension.NetCore.ServerInteractive/XFEExtension.NetCore.ServerInteractive.csproj +4 -0
@@ -61,4 +61,8 @@
61 61 <PackageReference Include="XFEExtension.NetCore.XFEConsole" Version="2.0.*" />
62 62 </ItemGroup>
63 63
64 <ItemGroup>
65 <ProjectReference Include="..\XFEExtension.NetCore.ServerInteractive.SourceGenerator\XFEExtension.NetCore.ServerInteractive.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
66 </ItemGroup>
67
64 68 </Project>