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

XFEExtension.NetCore.AutoConfig

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

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

XFEstudio/XFEExtension.NetCore.AutoConfig

准备分为多个类

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

代码差异

7 个文件 +269 -51
Modified AutoConfig.Analyzer.Test/Program.cs +3 -0
@@ -13,6 +13,9 @@ public class Program
13 13 SystemProfile.MyText = Console.ReadLine();
14 14 Console.WriteLine(SystemProfile.MyText);
15 15 Console.ReadLine();
16
17
18
16 19 //Console.WriteLine($"上一次读取的值是:{UserProfile.UserInfoList.ToJson()}");
17 20 //Console.WriteLine("添加值:");
18 21 //Console.WriteLine("请输入店铺名称:");
Modified AutoConfig.Analyzer.Test/SystemProfile.cs +7 -1
@@ -4,8 +4,14 @@ namespace AutoConfig.Analyzer.Test;
4 4
5 5 public partial class SystemProfile : XFEProfile
6 6 {
7
7 8 [ProfileProperty]
8 9 private string myText = "";
9 10 [ProfileProperty]
10 11 private int myInt = 1;
11 }
12
13 public SystemProfile()
14 {
15 DefaultProfileOperationMode = ProfileOperationMode.Json;
16 }
17 }
Modified AutoConfig.Analyzer.Test/UserProfile.cs +3 -1
@@ -11,5 +11,7 @@ internal partial class UserProfile : XFEProfile
11 11 /// 用户信息列表
12 12 /// </summary>
13 13 [ProfileProperty]
14 private ProfileList<UserProfile, UserInfo> userInfoList = [];
14 [ProfilePropertyAddGet("Current.userInfoList.CurrentProfile = Current")]
15 [ProfilePropertyAddGet("return Current.userInfoList")]
16 private ProfileList<UserInfo> userInfoList = [];
15 17 }
Modified XFEExtension.NetCore.AutoConfig.Analyzer/Generator/ProfilePropertyAutoGenerator.cs +209 -12
@@ -40,8 +40,8 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
40 40 var staticConstructorBlockStatements = new List<StatementSyntax>()
41 41 {
42 42 SyntaxFactory.ParseStatement($"Current = new {className}();"),
43 SyntaxFactory.ParseStatement($@"Current.ProfilePath = $""{{(string.IsNullOrEmpty(Current.ProfilePath) ? $""{{(global::XFEExtension.NetCore.AutoConfig.XFEProfile.ProfilesDefaultPath)}}\\{{nameof({className})}}"" : Current.ProfilePath)}}{{Current.ProfileFileExtension}}"";"),
44 SyntaxFactory.ParseStatement($"Current.SetProfileOperation();")
43 SyntaxFactory.ParseStatement($"Current.SetProfileOperation();"),
44 SyntaxFactory.ParseStatement($@"Current.ProfilePath = $""{{(string.IsNullOrEmpty(Current.ProfilePath) ? $""{{(global::XFEExtension.NetCore.AutoConfig.XFEProfile.ProfilesDefaultPath)}}\\{{nameof({className})}}"" : Current.ProfilePath)}}{{Current.ProfileFileExtension}}"";")
45 45 };
46 46 foreach (var fieldDeclarationSyntax in fieldDeclarationSyntaxes)
47 47 {
@@ -69,7 +69,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
69 69 #region Trivia头
70 70 var triviaText = $@"/// <inheritdoc cref=""{fieldName}""/>
71 71 /// <remarks>
72 /// <seealso cref=""{propertyName}""/> 是根据 <seealso cref=""{fieldName}""/> 自动生成的属性<br/><br/>
72 /// <seealso cref=""{propertyName}""/> 是根据 <seealso cref=""{fieldName}""/> 自动生成的静态属性<br/><br/>
73 73 /// <code><seealso langword=""get""/>方法已生成以下代码: ○ <seealso cref=""{className}.{getMethodName}()""/>;<br/>";
74 74 #endregion
75 75 var getExpressionStatements = new List<StatementSyntax>()
@@ -157,7 +157,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
157 157 /// </remarks>
158 158 ";
159 159 #endregion
160 var property = SyntaxFactory.PropertyDeclaration(propertyType, propertyName)
160 var staticProperty = SyntaxFactory.PropertyDeclaration(propertyType, propertyName)
161 161 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
162 162 .AddAttributeLists(attributeSyntax)
163 163 .WithAccessorList(SyntaxFactory.AccessorList(
@@ -178,7 +178,22 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
178 178 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
179 179 members.Add(getMethod);
180 180 members.Add(setMethod);
181 properties.Add(property.NormalizeWhitespace());
181 members.Add(SyntaxFactory.PropertyDeclaration(propertyType, $"Instance{propertyName}")
182 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)))
183 .AddAttributeLists(attributeSyntax)
184 .WithAccessorList(SyntaxFactory.AccessorList(
185 SyntaxFactory.List(
186 [
187 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
188 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.{fieldName}"))),
189 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
190 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.{fieldName} = value")))
191 ])))
192 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <inheritdoc cref=""{fieldName}""/>
193 /// <remarks>
194 /// <seealso cref=""{propertyName}""/> 是根据 <seealso cref=""{fieldName}""/> 自动生成的实例属性
195 /// </remarks>")));
196 properties.Add(staticProperty.NormalizeWhitespace());
182 197 }
183 198 staticConstructorBlockStatements.Add(SyntaxFactory.ParseStatement($"{className}.LoadProfile();"));
184 199 var staticConstructorSyntax = SyntaxFactory.ConstructorDeclaration(className)
@@ -204,7 +219,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
204 219 {
205 220 members.Add(staticConstructorSyntax);
206 221 }
207 var profileClassSyntaxTree = GenerateProfileClassSyntaxTree(classDeclaration, usingDirectives, properties, members, fileScopedNamespaceDeclarationSyntax);
222 var profileClassSyntaxTree = GenerateBasicProfileClassSyntaxTree(classDeclaration, usingDirectives, properties, members, fileScopedNamespaceDeclarationSyntax);
208 223 context.AddSource($"{className}.g.cs", profileClassSyntaxTree.ToString());
209 224 }
210 225 }
@@ -240,7 +255,93 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
240 255 public static IEnumerable<ClassDeclarationSyntax> GetClassDeclarations(SyntaxNode rootNode) => rootNode.DescendantNodes()
241 256 .OfType<ClassDeclarationSyntax>()
242 257 .Where(classDeclaration => classDeclaration.BaseList is not null && classDeclaration.BaseList.Types.Any(type => type.ToString() == "XFEProfile"));
243 private static SyntaxTree GenerateProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
258
259 private static SyntaxTree GenerateBasicProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
260 {
261 var className = classDeclaration.Identifier.ValueText;
262 memberDeclarationSyntaxes.Add(SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Current")
263 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
264 .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.AutoConfig.ProfileInstanceAttribute")))))
265 .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(
266 [
267 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
268 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
269 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
270 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
271 ])))
272 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
273 /// 该配置文件的实例<br/><br/>
274 /// <seealso cref=""{className}.Current""/> 是 <seealso cref=""{className}""/> 配置文件类的实例数据
275 /// </summary>
276 ")));
277 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "LoadProfile")
278 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
279 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceLoadProfile() as {className}")))
280 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
281 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
282 /// 配置文件加载方法<br/><br/>
283 /// <seealso cref=""{className}.LoadProfile""/> 是根据 <seealso cref=""{className}""/> 生成的加载配置文件的静态方法
284 /// </summary>
285 ")));
286 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "SaveProfile")
287 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
288 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceSaveProfile()")))
289 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
290 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
291 /// 配置文件保存方法<br/><br/>
292 /// <seealso cref=""{className}.SaveProfile""/> 是根据 <seealso cref=""{className}""/> 生成的保存配置文件的静态方法
293 /// </summary>
294 ")));
295 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("string"), "ExportProfile")
296 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
297 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceExportProfile()")))
298 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
299 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
300 /// 配置文件导出方法<br/><br/>
301 /// <seealso cref=""{className}.ExportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导出配置文件的静态方法
302 /// </summary>
303 /// <returns>导出的配置文件字符串</returns>
304 ")));
305 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "ImportProfile")
306 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
307 .AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier("profileString")).WithType(SyntaxFactory.ParseTypeName("string")))
308 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceImportProfile(profileString) as {className}")))
309 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
310 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
311 /// 配置文件导入方法<br/><br/>
312 /// <seealso cref=""{className}.ImportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导入配置文件的静态方法
313 /// </summary>
314 /// <param name=""profileString"">待导入配置文件字符串</param>
315 ")));
316 var profileClass = SyntaxFactory.ClassDeclaration(className)
317 .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
318 .AddMembers([.. memberDeclarationSyntaxes])
319 .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 var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
338 .AddUsings(usingDirectiveSyntaxes)
339 .AddMembers(memberDeclaration)
340 .NormalizeWhitespace();
341 return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
342 }
343
344 private static SyntaxTree GenerateProfileStaticPropertyClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
244 345 {
245 346 var className = classDeclaration.Identifier.ValueText;
246 347 var triviaText = $@"/// <remarks>
@@ -259,7 +360,97 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
259 360 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
260 361 ])))
261 362 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
262 /// 该配置文件的实例<br/>
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)));
410 memberDeclarationSyntaxes.AddRange(propertyDeclarationSyntaxes);
411 var profileClass = SyntaxFactory.ClassDeclaration(className)
412 .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
413 .AddMembers([.. memberDeclarationSyntaxes])
414 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText))
415 .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 var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
434 .AddUsings(usingDirectiveSyntaxes)
435 .AddMembers(memberDeclaration)
436 .NormalizeWhitespace();
437 return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
438 }
439 private static SyntaxTree GenerateProfileMethodClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MemberDeclarationSyntax> memberDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
440 {
441 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/>
263 454 /// <seealso cref=""{className}.Current""/> 是 <seealso cref=""{className}""/> 配置文件类的实例数据
264 455 /// </summary>
265 456 ")));
@@ -268,7 +459,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
268 459 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceLoadProfile() as {className}")))
269 460 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
270 461 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
271 /// 配置文件加载方法<br/>
462 /// 配置文件加载方法<br/><br/>
272 463 /// <seealso cref=""{className}.LoadProfile""/> 是根据 <seealso cref=""{className}""/> 生成的加载配置文件的静态方法
273 464 /// </summary>
274 465 ")));
@@ -277,7 +468,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
277 468 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceSaveProfile()")))
278 469 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
279 470 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
280 /// 配置文件保存方法<br/>
471 /// 配置文件保存方法<br/><br/>
281 472 /// <seealso cref=""{className}.SaveProfile""/> 是根据 <seealso cref=""{className}""/> 生成的保存配置文件的静态方法
282 473 /// </summary>
283 474 ")));
@@ -286,7 +477,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
286 477 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceExportProfile()")))
287 478 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
288 479 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
289 /// 配置文件导出方法<br/>
480 /// 配置文件导出方法<br/><br/>
290 481 /// <seealso cref=""{className}.ExportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导出配置文件的静态方法
291 482 /// </summary>
292 483 /// <returns>导出的配置文件字符串</returns>
@@ -297,11 +488,15 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
297 488 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceImportProfile(profileString) as {className}")))
298 489 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
299 490 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
300 /// 配置文件导入方法<br/>
491 /// 配置文件导入方法<br/><br/>
301 492 /// <seealso cref=""{className}.ImportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导入配置文件的静态方法
302 493 /// </summary>
303 494 /// <param name=""profileString"">待导入配置文件字符串</param>
304 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)));
305 500 memberDeclarationSyntaxes.AddRange(propertyDeclarationSyntaxes);
306 501 var profileClass = SyntaxFactory.ClassDeclaration(className)
307 502 .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
@@ -316,11 +511,13 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
316 511 memberDeclaration = profileClass;
317 512 else
318 513 memberDeclaration = SyntaxFactory.NamespaceDeclaration(namespaceDeclaration.Name)
514 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
319 515 .AddMembers(profileClass);
320 516 }
321 517 else
322 518 {
323 519 memberDeclaration = SyntaxFactory.FileScopedNamespaceDeclaration(fileScopedNamespaceDeclarationSyntax.Name)
520 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia("#pragma warning disable\n#nullable enable"))
324 521 .AddMembers(profileClass);
325 522 }
326 523 var profileClassCompilationUnit = SyntaxFactory.CompilationUnit()
Modified XFEExtension.NetCore.AutoConfig/ProfileDictionary.cs +14 -10
@@ -7,10 +7,9 @@ namespace XFEExtension.NetCore.AutoConfig;
7 7 /// <summary>
8 8 /// 配置文件字典
9 9 /// </summary>
10 /// <typeparam name="TProfile">配置文件类型</typeparam>
11 10 /// <typeparam name="TKey">字典Key泛型</typeparam>
12 11 /// <typeparam name="TValue">字典Value泛型</typeparam>
13 public class ProfileDictionary<TProfile, TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, ICollection, IDictionary, IDeserializationCallback, ISerializable where TKey : notnull
12 public class ProfileDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, ICollection, IDictionary, IDeserializationCallback, ISerializable where TKey : notnull
14 13 {
15 14 private readonly Dictionary<TKey, TValue> _innerDictionary;
16 15
@@ -33,6 +32,11 @@ public class ProfileDictionary<TProfile, TKey, TValue> : ICollection<KeyValuePai
33 32 ///<inheritdoc/>
34 33 public int Count => ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).Count;
35 34
35 /// <summary>
36 /// 当前配置文件实例
37 /// </summary>
38 public XFEProfile? CurrentProfile { get; set; }
39
36 40 ///<inheritdoc/>
37 41 public bool IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).IsReadOnly;
38 42
@@ -63,28 +67,28 @@ public class ProfileDictionary<TProfile, TKey, TValue> : ICollection<KeyValuePai
63 67 public void Add(KeyValuePair<TKey, TValue> item)
64 68 {
65 69 ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).Add(item);
66 XFEProfile.SaveProfile(typeof(TProfile));
70 CurrentProfile?.InstanceSaveProfile();
67 71 }
68 72
69 73 ///<inheritdoc/>
70 74 public void Add(TKey key, TValue value)
71 75 {
72 76 ((IDictionary<TKey, TValue>)_innerDictionary).Add(key, value);
73 XFEProfile.SaveProfile(typeof(TProfile));
77 CurrentProfile?.InstanceSaveProfile();
74 78 }
75 79
76 80 ///<inheritdoc/>
77 81 public void Add(object key, object? value)
78 82 {
79 83 ((IDictionary)_innerDictionary).Add(key, value);
80 XFEProfile.SaveProfile(typeof(TProfile));
84 CurrentProfile?.InstanceSaveProfile();
81 85 }
82 86
83 87 ///<inheritdoc/>
84 88 public void Clear()
85 89 {
86 90 ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).Clear();
87 XFEProfile.SaveProfile(typeof(TProfile));
91 CurrentProfile?.InstanceSaveProfile();
88 92 }
89 93
90 94 ///<inheritdoc/>
@@ -119,7 +123,7 @@ public class ProfileDictionary<TProfile, TKey, TValue> : ICollection<KeyValuePai
119 123 public bool Remove(KeyValuePair<TKey, TValue> item)
120 124 {
121 125 var result = ((ICollection<KeyValuePair<TKey, TValue>>)_innerDictionary).Remove(item);
122 XFEProfile.SaveProfile(typeof(TProfile));
126 CurrentProfile?.InstanceSaveProfile();
123 127 return result;
124 128 }
125 129
@@ -127,7 +131,7 @@ public class ProfileDictionary<TProfile, TKey, TValue> : ICollection<KeyValuePai
127 131 public bool Remove(TKey key)
128 132 {
129 133 var result = ((IDictionary<TKey, TValue>)_innerDictionary).Remove(key);
130 XFEProfile.SaveProfile(typeof(TProfile));
134 CurrentProfile?.InstanceSaveProfile();
131 135 return result;
132 136 }
133 137
@@ -135,7 +139,7 @@ public class ProfileDictionary<TProfile, TKey, TValue> : ICollection<KeyValuePai
135 139 public void Remove(object key)
136 140 {
137 141 ((IDictionary)_innerDictionary).Remove(key);
138 XFEProfile.SaveProfile(typeof(TProfile));
142 CurrentProfile?.InstanceSaveProfile();
139 143 }
140 144
141 145 ///<inheritdoc/>
@@ -145,7 +149,7 @@ public class ProfileDictionary<TProfile, TKey, TValue> : ICollection<KeyValuePai
145 149 public bool TryAdd(TKey key, TValue value)
146 150 {
147 151 var result = _innerDictionary.TryAdd(key, value);
148 XFEProfile.SaveProfile(typeof(TProfile));
152 CurrentProfile?.InstanceSaveProfile();
149 153 return result;
150 154 }
151 155
Modified XFEExtension.NetCore.AutoConfig/ProfileList.cs +16 -12
@@ -5,9 +5,8 @@ namespace XFEExtension.NetCore.AutoConfig;
5 5 /// <summary>
6 6 /// 配置文件列表
7 7 /// </summary>
8 /// <typeparam name="TProfile">配置文件类型</typeparam>
9 8 /// <typeparam name="TValue">列表泛型</typeparam>
10 public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TValue>, IEnumerable, IList<TValue>, IReadOnlyCollection<TValue>, IReadOnlyList<TValue>, ICollection, IList where TProfile : XFEProfile
9 public class ProfileList<TValue> : ICollection<TValue>, IEnumerable<TValue>, IEnumerable, IList<TValue>, IReadOnlyCollection<TValue>, IReadOnlyList<TValue>, ICollection, IList
11 10 {
12 11 private readonly List<TValue> _innerList;
13 12
@@ -26,6 +25,11 @@ public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TV
26 25 public TValue this[int index] { get => ((IList<TValue>)_innerList)[index]; set => ((IList<TValue>)_innerList)[index] = value; }
27 26 object? IList.this[int index] { get => ((IList)_innerList)[index]; set => ((IList)_innerList)[index] = value; }
28 27
28 /// <summary>
29 /// 当前配置文件实例
30 /// </summary>
31 public XFEProfile? CurrentProfile { get; set; }
32
29 33 ///<inheritdoc/>
30 34 public int Count => ((ICollection<TValue>)_innerList).Count;
31 35
@@ -45,14 +49,14 @@ public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TV
45 49 public void Add(TValue item)
46 50 {
47 51 ((ICollection<TValue>)_innerList).Add(item);
48 XFEProfile.SaveProfile(typeof(TProfile));
52 CurrentProfile?.InstanceSaveProfile();
49 53 }
50 54
51 55 ///<inheritdoc/>
52 56 public int Add(object? value)
53 57 {
54 58 var result = ((IList)_innerList).Add(value);
55 XFEProfile.SaveProfile(typeof(TProfile));
59 CurrentProfile?.InstanceSaveProfile();
56 60 return result;
57 61 }
58 62
@@ -60,21 +64,21 @@ public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TV
60 64 public void AddRange(IEnumerable<TValue> collection)
61 65 {
62 66 _innerList.AddRange(collection);
63 XFEProfile.SaveProfile(typeof(TProfile));
67 CurrentProfile?.InstanceSaveProfile();
64 68 }
65 69
66 70 ///<inheritdoc/>
67 71 public void AddRange(ReadOnlySpan<TValue> source)
68 72 {
69 73 _innerList.AddRange(source);
70 XFEProfile.SaveProfile(typeof(TProfile));
74 CurrentProfile?.InstanceSaveProfile();
71 75 }
72 76
73 77 ///<inheritdoc/>
74 78 public void Clear()
75 79 {
76 80 ((ICollection<TValue>)_innerList).Clear();
77 XFEProfile.SaveProfile(typeof(TProfile));
81 CurrentProfile?.InstanceSaveProfile();
78 82 }
79 83
80 84 ///<inheritdoc/>
@@ -102,21 +106,21 @@ public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TV
102 106 public void Insert(int index, TValue item)
103 107 {
104 108 ((IList<TValue>)_innerList).Insert(index, item);
105 XFEProfile.SaveProfile(typeof(TProfile));
109 CurrentProfile?.InstanceSaveProfile();
106 110 }
107 111
108 112 ///<inheritdoc/>
109 113 public void Insert(int index, object? value)
110 114 {
111 115 ((IList)_innerList).Insert(index, value);
112 XFEProfile.SaveProfile(typeof(TProfile));
116 CurrentProfile?.InstanceSaveProfile();
113 117 }
114 118
115 119 ///<inheritdoc/>
116 120 public bool Remove(TValue item)
117 121 {
118 122 var result = ((ICollection<TValue>)_innerList).Remove(item);
119 XFEProfile.SaveProfile(typeof(TProfile));
123 CurrentProfile?.InstanceSaveProfile();
120 124 return result;
121 125 }
122 126
@@ -124,14 +128,14 @@ public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TV
124 128 public void Remove(object? value)
125 129 {
126 130 ((IList)_innerList).Remove(value);
127 XFEProfile.SaveProfile(typeof(TProfile));
131 CurrentProfile?.InstanceSaveProfile();
128 132 }
129 133
130 134 ///<inheritdoc/>
131 135 public void RemoveAt(int index)
132 136 {
133 137 ((IList<TValue>)_innerList).RemoveAt(index);
134 XFEProfile.SaveProfile(typeof(TProfile));
138 CurrentProfile?.InstanceSaveProfile();
135 139 }
136 140
137 141 IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_innerList).GetEnumerator();
Modified XFEExtension.NetCore.AutoConfig/XFEProfile.cs +17 -15
@@ -18,35 +18,35 @@ public abstract class XFEProfile
18 18 /// <summary>
19 19 /// 配置文件存储位置
20 20 /// </summary>
21 public string ProfilePath { get; set; } = string.Empty;
21 internal protected string ProfilePath { get; set; } = string.Empty;
22 22 /// <summary>
23 23 /// 配置文件扩展名
24 24 /// </summary>
25 public string ProfileFileExtension { get; set; } = ".xpf";
25 internal protected string ProfileFileExtension { get; set; } = ".xpf";
26 26 /// <summary>
27 27 /// 默认配置文件存储和读取的操作模式
28 28 /// </summary>
29 public ProfileOperationMode DefaultProfileOperationMode { get; set; } = ProfileOperationMode.XFEDictionary;
29 internal protected ProfileOperationMode DefaultProfileOperationMode { get; set; } = ProfileOperationMode.XFEDictionary;
30 30 /// <summary>
31 31 /// 加载操作
32 32 /// </summary>
33 public ProfileLoadOperation LoadOperation { get; set; } = XFEDictionaryLoadProfileOperation;
33 internal protected ProfileLoadOperation LoadOperation { get; set; } = XFEDictionaryLoadProfileOperation;
34 34 /// <summary>
35 35 /// 保存操作
36 36 /// </summary>
37 public ProfileSaveOperation SaveOperation { get; set; } = XFEDictionarySaveProfileOperation;
37 internal protected ProfileSaveOperation SaveOperation { get; set; } = XFEDictionarySaveProfileOperation;
38 38 /// <summary>
39 39 /// 配置文件 “属性名称-属性类型” 字典
40 40 /// </summary>
41 public Dictionary<string, Type> PropertyInfoDictionary { get; set; } = [];
41 internal protected Dictionary<string, Type> PropertyInfoDictionary { get; set; } = [];
42 42 /// <summary>
43 43 /// 配置文件 “属性名称-属性设置方法” 字典
44 44 /// </summary>
45 public Dictionary<string, SetValueDelegate> PropertySetFuncDictionary { get; set; } = [];
45 internal protected Dictionary<string, SetValueDelegate> PropertySetFuncDictionary { get; set; } = [];
46 46 /// <summary>
47 47 /// 配置文件 “属性名称-属性获取方法” 字典
48 48 /// </summary>
49 public Dictionary<string, GetValueDelegate> PropertyGetFuncDictionary { get; set; } = [];
49 internal protected Dictionary<string, GetValueDelegate> PropertyGetFuncDictionary { get; set; } = [];
50 50 /// <summary>
51 51 /// 通过XFE字典加载配置文件方法(默认)
52 52 /// </summary>
@@ -129,18 +129,17 @@ public abstract class XFEProfile
129 129 /// 加载配置文件
130 130 /// </summary>
131 131 /// <returns>配置文件实例</returns>
132 public XFEProfile InstanceLoadProfile()
132 internal protected XFEProfile InstanceLoadProfile()
133 133 {
134 134 if (File.Exists(ProfilePath))
135 135 return LoadOperation(this, File.ReadAllText(ProfilePath), PropertyInfoDictionary, PropertySetFuncDictionary);
136 136 return this;
137 137 }
138
139 138 /// <summary>
140 139 /// 保存配置文件
141 140 /// </summary>
142 141 /// <returns>保存内容</returns>
143 public void InstanceSaveProfile()
142 internal protected void InstanceSaveProfile()
144 143 {
145 144 var saveContent = SaveOperation(this, PropertyInfoDictionary, PropertyGetFuncDictionary);
146 145 var fileSavePath = Path.GetDirectoryName(ProfilePath);
@@ -152,7 +151,7 @@ public abstract class XFEProfile
152 151 /// <summary>
153 152 /// 删除配置文件
154 153 /// </summary>
155 public void InstanceDeleteProfile()
154 internal protected void InstanceDeleteProfile()
156 155 {
157 156 if (File.Exists(ProfilePath))
158 157 File.Delete(ProfilePath);
@@ -161,31 +160,34 @@ public abstract class XFEProfile
161 160 /// 导出配置文件
162 161 /// </summary>
163 162 /// <returns></returns>
164 public string InstanceExportProfile() => SaveOperation(this, PropertyInfoDictionary, PropertyGetFuncDictionary);
163 internal protected string InstanceExportProfile() => SaveOperation(this, PropertyInfoDictionary, PropertyGetFuncDictionary);
165 164 /// <summary>
166 165 /// 导入配置文件
167 166 /// </summary>
168 167 /// <param name="profileString">配置文件字符串</param>
169 168 /// <returns></returns>
170 public XFEProfile InstanceImportProfile(string profileString) => LoadOperation(this, profileString, PropertyInfoDictionary, PropertySetFuncDictionary);
169 internal protected XFEProfile InstanceImportProfile(string profileString) => LoadOperation(this, profileString, PropertyInfoDictionary, PropertySetFuncDictionary);
171 170 /// <summary>
172 171 /// 设置配置文件加载和存储操作
173 172 /// </summary>
174 public void SetProfileOperation()
173 internal protected void SetProfileOperation()
175 174 {
176 175 switch (DefaultProfileOperationMode)
177 176 {
178 177 case ProfileOperationMode.XFEDictionary:
179 178 LoadOperation = XFEDictionaryLoadProfileOperation;
180 179 SaveOperation = XFEDictionarySaveProfileOperation;
180 ProfileFileExtension = ".xpf";
181 181 break;
182 182 case ProfileOperationMode.Json:
183 183 LoadOperation = JsonLoadProfileOperation;
184 184 SaveOperation = JsonSaveProfileOperation;
185 ProfileFileExtension = ".json";
185 186 break;
186 187 case ProfileOperationMode.Xml:
187 188 LoadOperation = XmlLoadProfileOperation;
188 189 SaveOperation = XmlSaveProfileOperation;
190 ProfileFileExtension = ".xml";
189 191 break;
190 192 case ProfileOperationMode.Custom:
191 193 break;