返回提交历史
Modified
AutoConfig.Analyzer.Test/Program.cs
+1
-0
Modified
AutoConfig.Analyzer.Test/SystemProfile.cs
+1
-2
Modified
XFEExtension.NetCore.AutoConfig.Analyzer/Generator/ProfilePropertyAutoGenerator.cs
+79
-190
Modified
XFEExtension.NetCore.AutoConfig/XFEProfile.cs
+10
-8
XFEstudio/XFEExtension.NetCore.AutoConfig
完善多个类的分离
d2aa2bb
代码差异
4 个文件
+91
-200
@@ -9,6 +9,7 @@ public class Program
9
9
public static void Main(string[] args)
10
10
{
11
11
Console.WriteLine($"上一次读取的值是{SystemProfile.MyText}");
12
var current = SystemProfile.Current;
12
13
Console.Write("添加值:");
13
14
SystemProfile.MyText = Console.ReadLine();
14
15
Console.WriteLine(SystemProfile.MyText);
@@ -4,11 +4,10 @@ namespace AutoConfig.Analyzer.Test;
4
4
5
5
public partial class SystemProfile : XFEProfile
6
6
{
7
8
7
[ProfileProperty]
9
8
private string myText = "";
10
9
[ProfileProperty]
11
private int myInt = 1;
10
private int myInt = 0;
12
11
13
12
public SystemProfile()
14
13
{
@@ -35,8 +35,10 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
35
35
var attributeSyntax = SyntaxFactory.AttributeList(
36
36
SyntaxFactory.SingletonSeparatedList(
37
37
SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.AutoConfig.ProfileFieldAutoGenerateAttribute"))));
38
var properties = new List<PropertyDeclarationSyntax>();
39
var members = new List<MemberDeclarationSyntax>();
38
var staticProperties = new List<PropertyDeclarationSyntax>();
39
var instanceProperties = new List<PropertyDeclarationSyntax>();
40
var basicProfileMembers = new List<MemberDeclarationSyntax>();
41
var methodMembers = new List<MemberDeclarationSyntax>();
40
42
var staticConstructorBlockStatements = new List<StatementSyntax>()
41
43
{
42
44
SyntaxFactory.ParseStatement($"Current = new {className}();"),
@@ -49,6 +51,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
49
51
var fieldName = variableDeclaration.Identifier.Text;
50
52
var propertyName = fieldName[0] == '_' ? fieldName[1].ToString().ToUpper() + fieldName.Substring(2) : fieldName[0].ToString().ToUpper() + fieldName.Substring(1);
51
53
var propertyType = fieldDeclarationSyntax.Declaration.Type;
54
var instancePropertyName = $"Instance{propertyName}";
52
55
var getMethodName = $"Get{propertyName}Property";
53
56
var setMethodName = $"Set{propertyName}Property";
54
57
staticConstructorBlockStatements.Add(SyntaxFactory.ParseStatement($"Current.PropertyInfoDictionary.Add(nameof({propertyName}), typeof({propertyType}));"));
@@ -171,29 +174,40 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
171
174
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText));
172
175
var getMethod = SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), getMethodName)
173
176
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)))
174
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
177
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
178
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
179
/// 当且仅当 <seealso cref=""{className}.{propertyName}""/> 被获取时触发此方法
180
/// </summary>
181
"));
175
182
var setMethod = SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), setMethodName)
176
183
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)))
177
184
.AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier("value")).WithType(propertyType).WithModifiers([SyntaxFactory.Token(SyntaxKind.RefKeyword)]))
178
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
179
members.Add(getMethod);
180
members.Add(setMethod);
181
members.Add(SyntaxFactory.PropertyDeclaration(propertyType, $"Instance{propertyName}")
185
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
186
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
187
/// 当且仅当 <seealso cref=""{className}.{propertyName}""/> 被赋值时触发此方法
188
/// </summary>
189
"));
190
methodMembers.Add(getMethod);
191
methodMembers.Add(setMethod);
192
instanceProperties.Add(SyntaxFactory.PropertyDeclaration(propertyType, instancePropertyName)
182
193
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)))
183
194
.AddAttributeLists(attributeSyntax)
184
195
.WithAccessorList(SyntaxFactory.AccessorList(
185
196
SyntaxFactory.List(
186
197
[
187
198
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
188
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.{fieldName}"))),
199
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"{fieldName}")))
200
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
189
201
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
190
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.{fieldName} = value")))
202
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"{fieldName} = value")))
203
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
191
204
])))
192
205
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <inheritdoc cref=""{fieldName}""/>
193
206
/// <remarks>
194
207
/// <seealso cref=""{propertyName}""/> 是根据 <seealso cref=""{fieldName}""/> 自动生成的实例属性
195
/// </remarks>")));
196
properties.Add(staticProperty.NormalizeWhitespace());
208
/// </remarks>
209
")));
210
staticProperties.Add(staticProperty.NormalizeWhitespace());
197
211
}
198
212
staticConstructorBlockStatements.Add(SyntaxFactory.ParseStatement($"{className}.LoadProfile();"));
199
213
var staticConstructorSyntax = SyntaxFactory.ConstructorDeclaration(className)
@@ -207,20 +221,26 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
207
221
var argument = autoLoadProfileAttribute.ArgumentList.Arguments.First();
208
222
if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && literalExpressionSyntax.Token.ValueText == "true")
209
223
{
210
members.Add(staticConstructorSyntax);
224
basicProfileMembers.Add(staticConstructorSyntax);
211
225
}
212
226
}
213
227
else
214
228
{
215
members.Add(staticConstructorSyntax);
229
basicProfileMembers.Add(staticConstructorSyntax);
216
230
}
217
231
}
218
232
else
219
233
{
220
members.Add(staticConstructorSyntax);
234
basicProfileMembers.Add(staticConstructorSyntax);
221
235
}
222
var profileClassSyntaxTree = GenerateBasicProfileClassSyntaxTree(classDeclaration, usingDirectives, properties, members, fileScopedNamespaceDeclarationSyntax);
223
context.AddSource($"{className}.g.cs", profileClassSyntaxTree.ToString());
236
var basicProfileClassSyntaxTree = GenerateBasicProfileClassSyntaxTree(classDeclaration, usingDirectives, basicProfileMembers, fileScopedNamespaceDeclarationSyntax);
237
var profileStaticPropertyClassSyntaxTree = GenerateProfileStaticPropertyClassSyntaxTree(classDeclaration, usingDirectives, staticProperties, fileScopedNamespaceDeclarationSyntax);
238
var profileInstancePropertyClassSyntaxTree = GenerateProfileInstancePropertyClassSyntaxTree(classDeclaration, usingDirectives, instanceProperties, fileScopedNamespaceDeclarationSyntax);
239
var profileMethodClassSyntaxTree = GenerateProfileMethodClassSyntaxTree(classDeclaration, usingDirectives, methodMembers, fileScopedNamespaceDeclarationSyntax);
240
context.AddSource($"{className}.g.cs", basicProfileClassSyntaxTree.ToString());
241
context.AddSource($"{className}.StaticProperties.g.cs", profileStaticPropertyClassSyntaxTree.ToString());
242
context.AddSource($"{className}.InstanceProperties.g.cs", profileInstancePropertyClassSyntaxTree.ToString());
243
context.AddSource($"{className}.Methods.g.cs", profileMethodClassSyntaxTree.ToString());
224
244
}
225
245
}
226
246
}
@@ -256,7 +276,27 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
256
276
.OfType<ClassDeclarationSyntax>()
257
277
.Where(classDeclaration => classDeclaration.BaseList is not null && classDeclaration.BaseList.Types.Any(type => type.ToString() == "XFEProfile"));
258
278
259
private static SyntaxTree GenerateBasicProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
279
private static MemberDeclarationSyntax GetClass(ClassDeclarationSyntax classDeclaration, ClassDeclarationSyntax profileClassDeclaration, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
280
{
281
if (fileScopedNamespaceDeclarationSyntax is null)
282
{
283
var namespaceDeclaration = classDeclaration.FirstAncestorOrSelf<NamespaceDeclarationSyntax>();
284
if (namespaceDeclaration is null)
285
return profileClassDeclaration;
286
else
287
return SyntaxFactory.NamespaceDeclaration(namespaceDeclaration.Name)
288
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
289
.AddMembers(profileClassDeclaration);
290
}
291
else
292
{
293
return SyntaxFactory.FileScopedNamespaceDeclaration(fileScopedNamespaceDeclarationSyntax.Name)
294
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
295
.AddMembers(profileClassDeclaration);
296
}
297
}
298
299
private static SyntaxTree GenerateBasicProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
260
300
{
261
301
var className = classDeclaration.Identifier.ValueText;
262
302
memberDeclarationSyntaxes.Add(SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Current")
@@ -317,31 +357,14 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
317
357
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
318
358
.AddMembers([.. memberDeclarationSyntaxes])
319
359
.NormalizeWhitespace();
320
MemberDeclarationSyntax memberDeclaration;
321
if (fileScopedNamespaceDeclarationSyntax is null)
322
{
323
var namespaceDeclaration = classDeclaration.FirstAncestorOrSelf<NamespaceDeclarationSyntax>();
324
if (namespaceDeclaration is null)
325
memberDeclaration = profileClass;
326
else
327
memberDeclaration = SyntaxFactory.NamespaceDeclaration(namespaceDeclaration.Name)
328
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
329
.AddMembers(profileClass);
330
}
331
else
332
{
333
memberDeclaration = SyntaxFactory.FileScopedNamespaceDeclaration(fileScopedNamespaceDeclarationSyntax.Name)
334
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
335
.AddMembers(profileClass);
336
}
337
360
var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
338
361
.AddUsings(usingDirectiveSyntaxes)
339
.AddMembers(memberDeclaration)
362
.AddMembers(GetClass(classDeclaration, profileClass, fileScopedNamespaceDeclarationSyntax))
340
363
.NormalizeWhitespace();
341
364
return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
342
365
}
343
366
344
private static SyntaxTree GenerateProfileStaticPropertyClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
367
private static SyntaxTree GenerateProfileStaticPropertyClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
345
368
{
346
369
var className = classDeclaration.Identifier.ValueText;
347
370
var triviaText = $@"/// <remarks>
@@ -349,180 +372,46 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
349
372
/// <code>
350
373
";
351
374
triviaText += string.Join("<br/>\n", propertyDeclarationSyntaxes.Select(propertyDeclarationSyntax => $"/// ○ <seealso cref=\"{propertyDeclarationSyntax.Identifier}\"/>")) + "\n/// </code><br/>\n/// <code>来自<seealso cref=\"global::XFEExtension.NetCore.AutoConfig.XFEProfile\"/></code>\n/// </remarks>\n";
352
memberDeclarationSyntaxes.Add(SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Current")
353
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
354
.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.AutoConfig.ProfileInstanceAttribute")))))
355
.WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(
356
[
357
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
358
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
359
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
360
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
361
])))
362
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
363
/// 该配置文件的实例<br/><br/>
364
/// <seealso cref=""{className}.Current""/> 是 <seealso cref=""{className}""/> 配置文件类的实例数据
365
/// </summary>
366
")));
367
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "LoadProfile")
368
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
369
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceLoadProfile() as {className}")))
370
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
371
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
372
/// 配置文件加载方法<br/><br/>
373
/// <seealso cref=""{className}.LoadProfile""/> 是根据 <seealso cref=""{className}""/> 生成的加载配置文件的静态方法
374
/// </summary>
375
")));
376
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "SaveProfile")
377
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
378
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceSaveProfile()")))
379
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
380
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
381
/// 配置文件保存方法<br/><br/>
382
/// <seealso cref=""{className}.SaveProfile""/> 是根据 <seealso cref=""{className}""/> 生成的保存配置文件的静态方法
383
/// </summary>
384
")));
385
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("string"), "ExportProfile")
386
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
387
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceExportProfile()")))
388
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
389
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
390
/// 配置文件导出方法<br/><br/>
391
/// <seealso cref=""{className}.ExportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导出配置文件的静态方法
392
/// </summary>
393
/// <returns>导出的配置文件字符串</returns>
394
")));
395
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "ImportProfile")
396
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
397
.AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier("profileString")).WithType(SyntaxFactory.ParseTypeName("string")))
398
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceImportProfile(profileString) as {className}")))
399
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
400
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
401
/// 配置文件导入方法<br/><br/>
402
/// <seealso cref=""{className}.ImportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导入配置文件的静态方法
403
/// </summary>
404
/// <param name=""profileString"">待导入配置文件字符串</param>
405
")));
406
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("global::XFEExtension.NetCore.AutoConfig.XFEProfile?"), "GetCurrent")
407
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ProtectedKeyword), SyntaxFactory.Token(SyntaxKind.OverrideKeyword)))
408
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression("Current")))
409
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)));
375
var memberDeclarationSyntaxes = new List<MemberDeclarationSyntax>();
410
376
memberDeclarationSyntaxes.AddRange(propertyDeclarationSyntaxes);
411
377
var profileClass = SyntaxFactory.ClassDeclaration(className)
412
378
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
413
379
.AddMembers([.. memberDeclarationSyntaxes])
414
380
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText))
415
381
.NormalizeWhitespace();
416
MemberDeclarationSyntax memberDeclaration;
417
if (fileScopedNamespaceDeclarationSyntax is null)
418
{
419
var namespaceDeclaration = classDeclaration.FirstAncestorOrSelf<NamespaceDeclarationSyntax>();
420
if (namespaceDeclaration is null)
421
memberDeclaration = profileClass;
422
else
423
memberDeclaration = SyntaxFactory.NamespaceDeclaration(namespaceDeclaration.Name)
424
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
425
.AddMembers(profileClass);
426
}
427
else
428
{
429
memberDeclaration = SyntaxFactory.FileScopedNamespaceDeclaration(fileScopedNamespaceDeclarationSyntax.Name)
430
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
431
.AddMembers(profileClass);
432
}
433
382
var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
434
383
.AddUsings(usingDirectiveSyntaxes)
435
.AddMembers(memberDeclaration)
384
.AddMembers(GetClass(classDeclaration, profileClass, fileScopedNamespaceDeclarationSyntax))
436
385
.NormalizeWhitespace();
437
386
return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
438
387
}
439
private static SyntaxTree GenerateProfileMethodClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
388
389
private static SyntaxTree GenerateProfileInstancePropertyClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
440
390
{
441
391
var className = classDeclaration.Identifier.ValueText;
442
memberDeclarationSyntaxes.Add(SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Current")
443
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
444
.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.AutoConfig.ProfileInstanceAttribute")))))
445
.WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(
446
[
447
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
448
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
449
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
450
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
451
])))
452
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
453
/// 该配置文件的实例<br/><br/>
454
/// <seealso cref=""{className}.Current""/> 是 <seealso cref=""{className}""/> 配置文件类的实例数据
455
/// </summary>
456
")));
457
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "LoadProfile")
458
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
459
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceLoadProfile() as {className}")))
460
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
461
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
462
/// 配置文件加载方法<br/><br/>
463
/// <seealso cref=""{className}.LoadProfile""/> 是根据 <seealso cref=""{className}""/> 生成的加载配置文件的静态方法
464
/// </summary>
465
")));
466
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "SaveProfile")
467
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
468
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceSaveProfile()")))
469
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
470
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
471
/// 配置文件保存方法<br/><br/>
472
/// <seealso cref=""{className}.SaveProfile""/> 是根据 <seealso cref=""{className}""/> 生成的保存配置文件的静态方法
473
/// </summary>
474
")));
475
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("string"), "ExportProfile")
476
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
477
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceExportProfile()")))
478
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
479
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
480
/// 配置文件导出方法<br/><br/>
481
/// <seealso cref=""{className}.ExportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导出配置文件的静态方法
482
/// </summary>
483
/// <returns>导出的配置文件字符串</returns>
484
")));
485
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "ImportProfile")
486
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
487
.AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier("profileString")).WithType(SyntaxFactory.ParseTypeName("string")))
488
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceImportProfile(profileString) as {className}")))
489
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
490
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
491
/// 配置文件导入方法<br/><br/>
492
/// <seealso cref=""{className}.ImportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导入配置文件的静态方法
493
/// </summary>
494
/// <param name=""profileString"">待导入配置文件字符串</param>
495
")));
496
memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("global::XFEExtension.NetCore.AutoConfig.XFEProfile?"), "GetCurrent")
497
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ProtectedKeyword), SyntaxFactory.Token(SyntaxKind.OverrideKeyword)))
498
.WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression("Current")))
499
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)));
392
var memberDeclarationSyntaxes = new List<MemberDeclarationSyntax>();
500
393
memberDeclarationSyntaxes.AddRange(propertyDeclarationSyntaxes);
501
394
var profileClass = SyntaxFactory.ClassDeclaration(className)
502
395
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
503
396
.AddMembers([.. memberDeclarationSyntaxes])
504
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText))
505
397
.NormalizeWhitespace();
506
MemberDeclarationSyntax memberDeclaration;
507
if (fileScopedNamespaceDeclarationSyntax is null)
508
{
509
var namespaceDeclaration = classDeclaration.FirstAncestorOrSelf<NamespaceDeclarationSyntax>();
510
if (namespaceDeclaration is null)
511
memberDeclaration = profileClass;
512
else
513
memberDeclaration = SyntaxFactory.NamespaceDeclaration(namespaceDeclaration.Name)
514
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
515
.AddMembers(profileClass);
516
}
517
else
518
{
519
memberDeclaration = SyntaxFactory.FileScopedNamespaceDeclaration(fileScopedNamespaceDeclarationSyntax.Name)
520
.WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
521
.AddMembers(profileClass);
522
}
523
398
var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
524
399
.AddUsings(usingDirectiveSyntaxes)
525
.AddMembers(memberDeclaration)
400
.AddMembers(GetClass(classDeclaration, profileClass, fileScopedNamespaceDeclarationSyntax))
401
.NormalizeWhitespace();
402
return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
403
}
404
405
private static SyntaxTree GenerateProfileMethodClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
406
{
407
var className = classDeclaration.Identifier.ValueText;
408
var profileClass = SyntaxFactory.ClassDeclaration(className)
409
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
410
.AddMembers([.. memberDeclarationSyntaxes])
411
.NormalizeWhitespace();
412
var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
413
.AddUsings(usingDirectiveSyntaxes)
414
.AddMembers(GetClass(classDeclaration, profileClass, fileScopedNamespaceDeclarationSyntax))
526
415
.NormalizeWhitespace();
527
416
return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
528
417
}
@@ -11,6 +11,7 @@ namespace XFEExtension.NetCore.AutoConfig;
11
11
/// </summary>
12
12
public abstract class XFEProfile
13
13
{
14
private string id = Guid.NewGuid().ToString();
14
15
/// <summary>
15
16
/// 配置文件所在的默认目录
16
17
/// </summary>
@@ -87,7 +88,8 @@ public abstract class XFEProfile
87
88
/// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
88
89
/// <param name="propertySetFuncDictionary">配置文件 “属性名称-属性设置方法” 字典</param>
89
90
/// <returns>配置文件实例</returns>
90
public static XFEProfile JsonLoadProfileOperation(XFEProfile profileInstance, string profileString, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, SetValueDelegate> propertySetFuncDictionary) => File.Exists(profileString) && JsonSerializer.Deserialize(profileString, profileInstance.GetType()) is XFEProfile xFEProfile ? xFEProfile : profileInstance;
91
public static XFEProfile JsonLoadProfileOperation(XFEProfile profileInstance, string profileString, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, SetValueDelegate> propertySetFuncDictionary) => JsonSerializer.Deserialize(profileString, profileInstance.GetType()) is XFEProfile xFEProfile ? xFEProfile : profileInstance;
92
91
93
/// <summary>
92
94
/// 通过Json保存配置文件方法
93
95
/// </summary>
@@ -95,12 +97,7 @@ public abstract class XFEProfile
95
97
/// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
96
98
/// <param name="propertyGetFuncDictionary">配置文件 “属性名称-属性值获取方法” 字典</param>
97
99
/// <returns>保存内容</returns>
98
public static string JsonSaveProfileOperation(XFEProfile profileInstance, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, GetValueDelegate> propertyGetFuncDictionary)
99
{
100
if (profileInstance is null)
101
return string.Empty;
102
return JsonSerializer.Serialize(profileInstance);
103
}
100
public static string JsonSaveProfileOperation(XFEProfile profileInstance, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, GetValueDelegate> propertyGetFuncDictionary) => profileInstance is null ? string.Empty : JsonSerializer.Serialize(profileInstance, profileInstance.GetType());
104
101
/// <summary>
105
102
/// 通过XML加载配置文件方法
106
103
/// </summary>
@@ -109,7 +106,7 @@ public abstract class XFEProfile
109
106
/// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
110
107
/// <param name="propertySetFuncDictionary">配置文件 “属性名称-属性设置方法” 字典</param>
111
108
/// <returns>配置文件实例</returns>
112
public static XFEProfile XmlLoadProfileOperation(XFEProfile profileInstance, string profileString, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, SetValueDelegate> propertySetFuncDictionary) => new XmlSerializer(profileInstance.GetType()).Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(profileString))) is XFEProfile xFEProfile ? xFEProfile : profileInstance;
109
public static XFEProfile XmlLoadProfileOperation(XFEProfile profileInstance, string profileString, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, SetValueDelegate> propertySetFuncDictionary) => string.IsNullOrEmpty(profileString) ? new XmlSerializer(profileInstance.GetType()).Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(profileString))) is XFEProfile xFEProfile ? xFEProfile : profileInstance : profileInstance;
113
110
/// <summary>
114
111
/// 通过XML保存配置文件方法
115
112
/// </summary>
@@ -123,6 +120,7 @@ public abstract class XFEProfile
123
120
return string.Empty;
124
121
using var stream = new MemoryStream();
125
122
new XmlSerializer(profileInstance.GetType()).Serialize(stream, profileInstance);
123
stream.Position = 0;
126
124
return new StreamReader(stream).ReadToEnd();
127
125
}
128
126
/// <summary>
@@ -195,6 +193,10 @@ public abstract class XFEProfile
195
193
break;
196
194
}
197
195
}
196
/// <summary>
197
/// 初始化
198
/// </summary>
199
protected virtual void Initialize() => SetProfileOperation();
198
200
#region 已过时
199
201
[Obsolete("SaveProfilesFunc属性现已过时,对于每个配置文件实例,请使用 XXXProfile.SaveOperation")]
200
202
private static Func<object?, ProfileEntryInfo, string> SaveProfilesFunc { get; set; } = (i, p) =>