XFEExtension.NetCore.ServerInteractive
[DLL] Server interaction extension, including user identity verification and querying in conjunction with AutoConfig
关注
0
Fork
0
Star
0
返回提交历史
Added
XFEExtension.NetCore.ServerInteractive.SourceGenerator/EntryPointGenerator.cs
+154
-0
Added
XFEExtension.NetCore.ServerInteractive.SourceGenerator/XFEExtension.NetCore.ServerInteractive.SourceGenerator.csproj
+20
-0
Modified
XFEExtension.NetCore.ServerInteractive.slnx
+1
-0
Modified
XFEExtension.NetCore.ServerInteractive/Implements/CoreService/ServerCoreStandardServiceBase.cs
+19
-5
Modified
XFEExtension.NetCore.ServerInteractive/Utilities/Server/XFEServerCore.cs
+37
-8
Modified
XFEExtension.NetCore.ServerInteractive/XFEExtension.NetCore.ServerInteractive.csproj
+4
-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
代码差异
6 个文件
+235
-13
@@ -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
}
@@ -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>
@@ -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>
@@ -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
}
@@ -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)
@@ -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>