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

XFEExtension.NetCore.AutoConfig

【DLL】自动实现配置文件的存储

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

XFEstudio/XFEExtension.NetCore.AutoConfig

完善多个类的分离

d2aa2bb
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

4 个文件 +91 -200
Modified AutoConfig.Analyzer.Test/Program.cs +1 -0
@@ -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);
Modified AutoConfig.Analyzer.Test/SystemProfile.cs +1 -2
@@ -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 {
Modified XFEExtension.NetCore.AutoConfig.Analyzer/Generator/ProfilePropertyAutoGenerator.cs +79 -190
@@ -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 }
Modified XFEExtension.NetCore.AutoConfig/XFEProfile.cs +10 -8
@@ -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) =>