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

XFEExtension.NetCore.AutoConfig

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

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

XFEstudio/XFEExtension.NetCore.AutoConfig

初步完成脱离反射的配置文件自动存储

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

代码差异

9 个文件 +382 -91
Modified AutoConfig.Analyzer.Test/Program.cs +31 -16
@@ -1,4 +1,5 @@
1 using PDDShopManagementSystem.ServerConsole;
1 using System.Text.Json;
2 using XFEExtension.NetCore.StringExtension;
2 3 using XFEExtension.NetCore.StringExtension.Json;
3 4
4 5 namespace AutoConfig.Analyzer.Test;
@@ -7,21 +8,35 @@ public class Program
7 8 {
8 9 public static void Main(string[] args)
9 10 {
10 Console.WriteLine($"上一次读取的值是:{UserProfile.UserInfoList.ToJson()}");
11 Console.WriteLine("添加值:");
12 Console.WriteLine("请输入店铺名称:");
13 var shopName = Console.ReadLine();
14 Console.WriteLine("请输入店铺ID:");
15 var shopID = Console.ReadLine() ?? "暂无ID";
16 UserProfile.UserInfoList.Add(new()
17 {
18 SessionID = Guid.NewGuid().ToString(),
19 ShopID = shopID,
20 RecentShopName = shopName,
21 CurrentIpAddress = "198.131.114.41",
22 Banned = false,
23 EndDateTime = DateTime.Now
24 });
11 Console.WriteLine($"上一次读取的值是{SystemProfile.MyText}");
12 Console.Write("添加值:");
13 SystemProfile.MyText = Console.ReadLine();
14 Console.WriteLine(SystemProfile.MyText);
25 15 Console.ReadLine();
16 //Console.WriteLine($"上一次读取的值是:{UserProfile.UserInfoList.ToJson()}");
17 //Console.WriteLine("添加值:");
18 //Console.WriteLine("请输入店铺名称:");
19 //var shopName = Console.ReadLine();
20 //Console.WriteLine("请输入店铺ID:");
21 //var shopID = Console.ReadLine() ?? "暂无ID";
22 //Console.WriteLine("创建对象...");
23 //var target = new UserInfo()
24 //{
25 // SessionID = Guid.NewGuid().ToString(),
26 // ShopID = shopID,
27 // RecentShopName = shopName,
28 // CurrentIpAddress = "198.131.114.41",
29 // Banned = false,
30 // EndDateTime = DateTime.Now
31 //};
32 //Console.WriteLine(target.ShopID);
33 //Console.WriteLine(JsonSerializer.Serialize(target));
34 //Console.WriteLine("对象创建完成!准备进行分析...");
35 //target.X();
36 //Console.WriteLine(target.ToJson());
37 //Console.WriteLine("分析完成!");
38 //UserProfile.UserInfoList.Add(target);
39 //Console.WriteLine(UserProfile.UserInfoList.ToJson());
40 //Console.ReadLine();
26 41 }
27 42 }
Modified AutoConfig.Analyzer.Test/SystemProfile.cs +3 -1
@@ -2,8 +2,10 @@
2 2
3 3 namespace AutoConfig.Analyzer.Test;
4 4
5 public partial class SystemProfile
5 public partial class SystemProfile : XFEProfile
6 6 {
7 7 [ProfileProperty]
8 8 private string myText = "";
9 [ProfileProperty]
10 private int myInt = 1;
9 11 }
Modified AutoConfig.Analyzer.Test/UserInfo.cs +1 -1
@@ -1,4 +1,4 @@
1 namespace PDDShopManagementSystem.ServerConsole;
1 namespace AutoConfig.Analyzer.Test;
2 2
3 3 /// <summary>
4 4 /// 用户信息
Modified AutoConfig.Analyzer.Test/UserProfile.cs +2 -2
@@ -1,11 +1,11 @@
1 1 using XFEExtension.NetCore.AutoConfig;
2 2
3 namespace PDDShopManagementSystem.ServerConsole;
3 namespace AutoConfig.Analyzer.Test;
4 4
5 5 /// <summary>
6 6 /// 用户配置文件
7 7 /// </summary>
8 internal partial class UserProfile
8 internal partial class UserProfile : XFEProfile
9 9 {
10 10 /// <summary>
11 11 /// 用户信息列表
Added ProfileOperationMode.cs +0 -0
此文件没有可显示的逐行差异。
Modified XFEExtension.NetCore.AutoConfig.Analyzer/Generator/ProfilePropertyAutoGenerator.cs +87 -63
@@ -36,14 +36,24 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
36 36 SyntaxFactory.SingletonSeparatedList(
37 37 SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.AutoConfig.ProfileFieldAutoGenerateAttribute"))));
38 38 var properties = new List<PropertyDeclarationSyntax>();
39 var methods = new List<MethodDeclarationSyntax>();
39 var members = new List<MemberDeclarationSyntax>();
40 var staticConstructorBlockStatements = new List<StatementSyntax>()
41 {
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();")
45 };
40 46 foreach (var fieldDeclarationSyntax in fieldDeclarationSyntaxes)
41 47 {
42 48 var variableDeclaration = fieldDeclarationSyntax.Declaration.Variables.First();
43 49 var fieldName = variableDeclaration.Identifier.Text;
44 50 var propertyName = fieldName[0] == '_' ? fieldName[1].ToString().ToUpper() + fieldName.Substring(2) : fieldName[0].ToString().ToUpper() + fieldName.Substring(1);
51 var propertyType = fieldDeclarationSyntax.Declaration.Type;
45 52 var getMethodName = $"Get{propertyName}Property";
46 53 var setMethodName = $"Set{propertyName}Property";
54 staticConstructorBlockStatements.Add(SyntaxFactory.ParseStatement($"Current.PropertyInfoDictionary.Add(nameof({propertyName}), typeof({propertyType}));"));
55 staticConstructorBlockStatements.Add(SyntaxFactory.ParseStatement($"Current.PropertySetFuncDictionary.Add(nameof({propertyName}), (value) => Current.{fieldName} = ({propertyType})value);"));
56 staticConstructorBlockStatements.Add(SyntaxFactory.ParseStatement($"Current.PropertyGetFuncDictionary.Add(nameof({propertyName}), () => Current.{fieldName});"));
47 57 GetProfilePropertyAttributeList(fieldDeclarationSyntax).ForEach(attribute =>
48 58 {
49 59 if (attribute.ArgumentList is null)
@@ -56,7 +66,6 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
56 66 propertyName = literalExpressionSyntax.Token.ValueText;
57 67 }
58 68 });
59 var propertyType = fieldDeclarationSyntax.Declaration.Type;
60 69 #region Trivia头
61 70 var triviaText = $@"/// <inheritdoc cref=""{fieldName}""/>
62 71 /// <remarks>
@@ -101,7 +110,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
101 110 triviaText += $@"
102 111 /// </code>
103 112 /// <br/>
104 /// <code><seealso langword=""set""/>方法已生成以下代码: ○ <seealso cref=""{className}.{setMethodName}({propertyType})""/>;<br/>";
113 /// <code><seealso langword=""set""/>方法已生成以下代码: ○ <seealso cref=""{className}.{setMethodName}(ref {propertyType})""/>;<br/>";
105 114 #endregion
106 115 var setExpressionStatements = new List<StatementSyntax>()
107 116 {
@@ -137,10 +146,10 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
137 146 /// ○ <seealso langword=""{fieldName}""/> = <seealso langword=""value""/>;<br/>";
138 147 #endregion
139 148 }
140 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"global::XFEExtension.NetCore.AutoConfig.XFEProfile.SaveProfile(new(typeof({className}), ProfilePath))")));
149 setExpressionStatements.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression($"{className}.SaveProfile()")));
141 150 #region Set方法中的保存方法的注释
142 151 triviaText += $@"
143 /// ○ <seealso cref=""global::XFEExtension.NetCore.AutoConfig.XFEProfile.SaveProfile(ProfileInfo)""/>";
152 /// ○ <seealso cref=""{className}.SaveProfile()""/>";
144 153 #endregion
145 154 #region Trivia尾
146 155 triviaText += @"
@@ -167,11 +176,35 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
167 176 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)))
168 177 .AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier("value")).WithType(propertyType).WithModifiers([SyntaxFactory.Token(SyntaxKind.RefKeyword)]))
169 178 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
170 methods.Add(getMethod);
171 methods.Add(setMethod);
179 members.Add(getMethod);
180 members.Add(setMethod);
172 181 properties.Add(property.NormalizeWhitespace());
173 182 }
174 var profileClassSyntaxTree = GenerateProfileClassSyntaxTree(classDeclaration, usingDirectives, properties, methods, fileScopedNamespaceDeclarationSyntax);
183 staticConstructorBlockStatements.Add(SyntaxFactory.ParseStatement($"{className}.LoadProfile();"));
184 var staticConstructorSyntax = SyntaxFactory.ConstructorDeclaration(className)
185 .AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword))
186 .WithBody(SyntaxFactory.Block(staticConstructorBlockStatements));
187 if (classDeclaration.AttributeLists.Any(IsAutoLoadProfileAttribute))
188 {
189 var autoLoadProfileAttribute = classDeclaration.AttributeLists.First(IsAutoLoadProfileAttribute).Attributes.First();
190 if (autoLoadProfileAttribute.ArgumentList != null)
191 {
192 var argument = autoLoadProfileAttribute.ArgumentList.Arguments.First();
193 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && literalExpressionSyntax.Token.ValueText == "true")
194 {
195 members.Add(staticConstructorSyntax);
196 }
197 }
198 else
199 {
200 members.Add(staticConstructorSyntax);
201 }
202 }
203 else
204 {
205 members.Add(staticConstructorSyntax);
206 }
207 var profileClassSyntaxTree = GenerateProfileClassSyntaxTree(classDeclaration, usingDirectives, properties, members, fileScopedNamespaceDeclarationSyntax);
175 208 context.AddSource($"{className}.g.cs", profileClassSyntaxTree.ToString());
176 209 }
177 210 }
@@ -206,9 +239,8 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
206 239
207 240 public static IEnumerable<ClassDeclarationSyntax> GetClassDeclarations(SyntaxNode rootNode) => rootNode.DescendantNodes()
208 241 .OfType<ClassDeclarationSyntax>()
209 .Where(classDeclaration => !classDeclaration.Modifiers.Any(SyntaxKind.StaticKeyword));
210
211 private static SyntaxTree GenerateProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, List<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, List<MethodDeclarationSyntax> methodDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
242 .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)
212 244 {
213 245 var className = classDeclaration.Identifier.ValueText;
214 246 var triviaText = $@"/// <remarks>
@@ -216,26 +248,7 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
216 248 /// <code>
217 249 ";
218 250 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";
219 var memberDeclarations = new List<MemberDeclarationSyntax>
220 {
221 SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName("string"), "ProfilePath")
222 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
223 .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(
224 [
225 SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
226 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
227 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
228 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
229 ])))
230 .WithInitializer(SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression(@"""""")))
231 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
232 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
233 /// 该配置文件的自动存储和读取路径<br/>
234 /// 设置的时候记得带上文件名和后缀<br/>
235 /// <seealso cref=""ProfilePath""/> 是 <seealso cref=""{className}""/> 配置文件类的自动存储读取路径
236 /// </summary>
237 ")),
238 SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Current")
251 memberDeclarationSyntaxes.Add(SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(className), "Current")
239 252 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
240 253 .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.AutoConfig.ProfileInstanceAttribute")))))
241 254 .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(
@@ -245,43 +258,54 @@ public class ProfilePropertyAutoGenerator : IIncrementalGenerator
245 258 SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
246 259 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
247 260 ])))
248 .WithInitializer(SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression($"new {className}()")))
249 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
250 261 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
251 262 /// 该配置文件的实例<br/>
252 /// <seealso cref=""Current""/> 是 <seealso cref=""{className}""/> 配置文件类的实例数据
263 /// <seealso cref=""{className}.Current""/> 是 <seealso cref=""{className}""/> 配置文件类的实例数据
253 264 /// </summary>
254 "))
255 };
256 memberDeclarations.AddRange(propertyDeclarationSyntaxes);
257 memberDeclarations.AddRange(methodDeclarationSyntaxes);
258 var staticConstructorSyntax = SyntaxFactory.ConstructorDeclaration(className)
259 .AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword))
260 .WithBody(SyntaxFactory.Block(
261 SyntaxFactory.ParseStatement($"global::XFEExtension.NetCore.AutoConfig.XFEProfile.LoadProfiles([new(typeof({className}), ProfilePath)]);")));
262 if (classDeclaration.AttributeLists.Any(IsAutoLoadProfileAttribute))
263 {
264 var autoLoadProfileAttribute = classDeclaration.AttributeLists.First(attributeList => IsAutoLoadProfileAttribute(attributeList)).Attributes.First();
265 if (autoLoadProfileAttribute.ArgumentList != null)
266 {
267 var argument = autoLoadProfileAttribute.ArgumentList.Arguments.First();
268 if (argument.Expression is LiteralExpressionSyntax literalExpressionSyntax && literalExpressionSyntax.Token.ValueText == "true")
269 {
270 memberDeclarations.Add(staticConstructorSyntax);
271 }
272 }
273 else
274 {
275 memberDeclarations.Add(staticConstructorSyntax);
276 }
277 }
278 else
279 {
280 memberDeclarations.Add(staticConstructorSyntax);
281 }
265 ")));
266 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "LoadProfile")
267 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
268 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceLoadProfile() as {className}")))
269 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
270 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
271 /// 配置文件加载方法<br/>
272 /// <seealso cref=""{className}.LoadProfile""/> 是根据 <seealso cref=""{className}""/> 生成的加载配置文件的静态方法
273 /// </summary>
274 ")));
275 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "SaveProfile")
276 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
277 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceSaveProfile()")))
278 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
279 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
280 /// 配置文件保存方法<br/>
281 /// <seealso cref=""{className}.SaveProfile""/> 是根据 <seealso cref=""{className}""/> 生成的保存配置文件的静态方法
282 /// </summary>
283 ")));
284 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("string"), "ExportProfile")
285 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
286 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current.InstanceExportProfile()")))
287 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
288 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
289 /// 配置文件导出方法<br/>
290 /// <seealso cref=""{className}.ExportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导出配置文件的静态方法
291 /// </summary>
292 /// <returns>导出的配置文件字符串</returns>
293 ")));
294 memberDeclarationSyntaxes.Add(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "ImportProfile")
295 .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
296 .AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier("profileString")).WithType(SyntaxFactory.ParseTypeName("string")))
297 .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression($"Current = Current.InstanceImportProfile(profileString) as {className}")))
298 .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
299 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia($@"/// <summary>
300 /// 配置文件导入方法<br/>
301 /// <seealso cref=""{className}.ImportProfile""/> 是根据 <seealso cref=""{className}""/> 生成的导入配置文件的静态方法
302 /// </summary>
303 /// <param name=""profileString"">待导入配置文件字符串</param>
304 ")));
305 memberDeclarationSyntaxes.AddRange(propertyDeclarationSyntaxes);
282 306 var profileClass = SyntaxFactory.ClassDeclaration(className)
283 307 .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword))
284 .AddMembers(memberDeclarations.ToArray())
308 .AddMembers([.. memberDeclarationSyntaxes])
285 309 .WithLeadingTrivia(SyntaxFactory.ParseLeadingTrivia(triviaText))
286 310 .NormalizeWhitespace();
287 311 MemberDeclarationSyntax memberDeclaration;
Modified XFEExtension.NetCore.AutoConfig/ProfileList.cs +1 -1
@@ -7,7 +7,7 @@ namespace XFEExtension.NetCore.AutoConfig;
7 7 /// </summary>
8 8 /// <typeparam name="TProfile">配置文件类型</typeparam>
9 9 /// <typeparam name="TValue">列表泛型</typeparam>
10 public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TValue>, IEnumerable, IList<TValue>, IReadOnlyCollection<TValue>, IReadOnlyList<TValue>, ICollection, IList
10 public class ProfileList<TProfile, TValue> : ICollection<TValue>, IEnumerable<TValue>, IEnumerable, IList<TValue>, IReadOnlyCollection<TValue>, IReadOnlyList<TValue>, ICollection, IList where TProfile : XFEProfile
11 11 {
12 12 private readonly List<TValue> _innerList;
13 13
Added XFEExtension.NetCore.AutoConfig/ProfileOperationMode.cs +24 -0
@@ -0,0 +1,24 @@
1 namespace XFEExtension.NetCore.AutoConfig;
2
3 /// <summary>
4 /// 配置文件存储和读取操作模式
5 /// </summary>
6 public enum ProfileOperationMode
7 {
8 /// <summary>
9 /// 使用XFE字典加载和存储配置文件(默认)
10 /// </summary>
11 XFEDictionary,
12 /// <summary>
13 /// 使用Json序列化加载和存储配置文件
14 /// </summary>
15 Json,
16 /// <summary>
17 /// 使用Xml序列化加载和存储配置文件
18 /// </summary>
19 Xml,
20 /// <summary>
21 /// 使用自定义方法加载和存储配置文件
22 /// </summary>
23 Custom
24 }
Modified XFEExtension.NetCore.AutoConfig/XFEProfile.cs +233 -7
@@ -1,5 +1,7 @@
1 1 using System.Reflection;
2 using System.Text;
2 3 using System.Text.Json;
4 using System.Xml.Serialization;
3 5 using XFEExtension.NetCore.FormatExtension;
4 6
5 7 namespace XFEExtension.NetCore.AutoConfig;
@@ -9,6 +11,190 @@ namespace XFEExtension.NetCore.AutoConfig;
9 11 /// </summary>
10 12 public abstract class XFEProfile
11 13 {
14 /// <summary>
15 /// 配置文件所在的默认目录
16 /// </summary>
17 public static string ProfilesDefaultPath { get; set; } = $"{AppDomain.CurrentDomain.BaseDirectory}/Profiles";
18 /// <summary>
19 /// 配置文件存储位置
20 /// </summary>
21 public string ProfilePath { get; set; } = string.Empty;
22 /// <summary>
23 /// 配置文件扩展名
24 /// </summary>
25 public string ProfileFileExtension { get; set; } = ".xpf";
26 /// <summary>
27 /// 默认配置文件存储和读取的操作模式
28 /// </summary>
29 public ProfileOperationMode DefaultProfileOperationMode { get; set; } = ProfileOperationMode.XFEDictionary;
30 /// <summary>
31 /// 加载操作
32 /// </summary>
33 public ProfileLoadOperation LoadOperation { get; set; } = XFEDictionaryLoadProfileOperation;
34 /// <summary>
35 /// 保存操作
36 /// </summary>
37 public ProfileSaveOperation SaveOperation { get; set; } = XFEDictionarySaveProfileOperation;
38 /// <summary>
39 /// 配置文件 “属性名称-属性类型” 字典
40 /// </summary>
41 public Dictionary<string, Type> PropertyInfoDictionary { get; set; } = [];
42 /// <summary>
43 /// 配置文件 “属性名称-属性设置方法” 字典
44 /// </summary>
45 public Dictionary<string, SetValueDelegate> PropertySetFuncDictionary { get; set; } = [];
46 /// <summary>
47 /// 配置文件 “属性名称-属性获取方法” 字典
48 /// </summary>
49 public Dictionary<string, GetValueDelegate> PropertyGetFuncDictionary { get; set; } = [];
50 /// <summary>
51 /// 通过XFE字典加载配置文件方法(默认)
52 /// </summary>
53 /// <param name="profileInstance">配置文件实例</param>
54 /// <param name="profileString">配置文件字符串</param>
55 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
56 /// <param name="propertySetFuncDictionary">配置文件 “属性名称-属性设置方法” 字典</param>
57 /// <returns>配置文件实例</returns>
58 public static XFEProfile XFEDictionaryLoadProfileOperation(XFEProfile profileInstance, string profileString, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, SetValueDelegate> propertySetFuncDictionary)
59 {
60 XFEDictionary propertyFileContent = profileString;
61 foreach (var property in propertyFileContent)
62 if (propertySetFuncDictionary.TryGetValue(property.Header, out var setValueDelegate) && propertyInfoDictionary.TryGetValue(property.Header, out var type))
63 setValueDelegate(JsonSerializer.Deserialize(property.Content, type));
64 return profileInstance;
65 }
66 /// <summary>
67 /// 通过XFE字典保存配置文件方法(默认)
68 /// </summary>
69 /// <param name="profileInstance">配置文件实例</param>
70 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
71 /// <param name="propertyGetFuncDictionary">配置文件 “属性名称-属性值获取方法” 字典</param>
72 /// <returns>保存内容</returns>
73 public static string XFEDictionarySaveProfileOperation(XFEProfile profileInstance, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, GetValueDelegate> propertyGetFuncDictionary)
74 {
75 if (profileInstance is null)
76 return string.Empty;
77 var saveProfileDictionary = new XFEDictionary();
78 foreach (var property in propertyGetFuncDictionary)
79 saveProfileDictionary.Add(property.Key, JsonSerializer.Serialize(property.Value()));
80 return saveProfileDictionary.ToString();
81 }
82 /// <summary>
83 /// 通过Json加载配置文件方法
84 /// </summary>
85 /// <param name="profileInstance">配置文件实例</param>
86 /// <param name="profileString">配置文件字符串</param>
87 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
88 /// <param name="propertySetFuncDictionary">配置文件 “属性名称-属性设置方法” 字典</param>
89 /// <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 /// <summary>
92 /// 通过Json保存配置文件方法
93 /// </summary>
94 /// <param name="profileInstance">配置文件实例</param>
95 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
96 /// <param name="propertyGetFuncDictionary">配置文件 “属性名称-属性值获取方法” 字典</param>
97 /// <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 }
104 /// <summary>
105 /// 通过XML加载配置文件方法
106 /// </summary>
107 /// <param name="profileInstance">配置文件实例</param>
108 /// <param name="profileString">配置文件字符串</param>
109 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
110 /// <param name="propertySetFuncDictionary">配置文件 “属性名称-属性设置方法” 字典</param>
111 /// <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;
113 /// <summary>
114 /// 通过XML保存配置文件方法
115 /// </summary>
116 /// <param name="profileInstance">配置文件实例</param>
117 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
118 /// <param name="propertyGetFuncDictionary">配置文件 “属性名称-属性值获取方法” 字典</param>
119 /// <returns>保存内容</returns>
120 public static string XmlSaveProfileOperation(XFEProfile profileInstance, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, GetValueDelegate> propertyGetFuncDictionary)
121 {
122 if (profileInstance is null)
123 return string.Empty;
124 using var stream = new MemoryStream();
125 new XmlSerializer(profileInstance.GetType()).Serialize(stream, profileInstance);
126 return new StreamReader(stream).ReadToEnd();
127 }
128 /// <summary>
129 /// 加载配置文件
130 /// </summary>
131 /// <returns>配置文件实例</returns>
132 public XFEProfile InstanceLoadProfile()
133 {
134 if (File.Exists(ProfilePath))
135 return LoadOperation(this, File.ReadAllText(ProfilePath), PropertyInfoDictionary, PropertySetFuncDictionary);
136 return this;
137 }
138
139 /// <summary>
140 /// 保存配置文件
141 /// </summary>
142 /// <returns>保存内容</returns>
143 public void InstanceSaveProfile()
144 {
145 var saveContent = SaveOperation(this, PropertyInfoDictionary, PropertyGetFuncDictionary);
146 var fileSavePath = Path.GetDirectoryName(ProfilePath);
147 if (!Directory.Exists(fileSavePath) && fileSavePath is not null && fileSavePath != string.Empty)
148 Directory.CreateDirectory(fileSavePath);
149 File.WriteAllTextAsync(ProfilePath, saveContent);
150 return;
151 }
152 /// <summary>
153 /// 删除配置文件
154 /// </summary>
155 public void InstanceDeleteProfile()
156 {
157 if (File.Exists(ProfilePath))
158 File.Delete(ProfilePath);
159 }
160 /// <summary>
161 /// 导出配置文件
162 /// </summary>
163 /// <returns></returns>
164 public string InstanceExportProfile() => SaveOperation(this, PropertyInfoDictionary, PropertyGetFuncDictionary);
165 /// <summary>
166 /// 导入配置文件
167 /// </summary>
168 /// <param name="profileString">配置文件字符串</param>
169 /// <returns></returns>
170 public XFEProfile InstanceImportProfile(string profileString) => LoadOperation(this, profileString, PropertyInfoDictionary, PropertySetFuncDictionary);
171 /// <summary>
172 /// 设置配置文件加载和存储操作
173 /// </summary>
174 public void SetProfileOperation()
175 {
176 switch (DefaultProfileOperationMode)
177 {
178 case ProfileOperationMode.XFEDictionary:
179 LoadOperation = XFEDictionaryLoadProfileOperation;
180 SaveOperation = XFEDictionarySaveProfileOperation;
181 break;
182 case ProfileOperationMode.Json:
183 LoadOperation = JsonLoadProfileOperation;
184 SaveOperation = JsonSaveProfileOperation;
185 break;
186 case ProfileOperationMode.Xml:
187 LoadOperation = XmlLoadProfileOperation;
188 SaveOperation = XmlSaveProfileOperation;
189 break;
190 case ProfileOperationMode.Custom:
191 break;
192 default:
193 break;
194 }
195 }
196 #region 已过时
197 [Obsolete("SaveProfilesFunc属性现已过时,对于每个配置文件实例,请使用 XXXProfile.SaveOperation")]
12 198 private static Func<object?, ProfileEntryInfo, string> SaveProfilesFunc { get; set; } = (i, p) =>
13 199 {
14 200 if (p.MemberInfo is FieldInfo fieldInfo)
@@ -18,6 +204,7 @@ public abstract class XFEProfile
18 204 else
19 205 return string.Empty;
20 206 };
207 [Obsolete("SaveProfilesFunc属性现已过时,对于每个配置文件实例,请使用 XXXProfile.LoadOperation")]
21 208 private static Func<string, ProfileEntryInfo, object?> LoadProfilesFunc { get; set; } = (x, p) =>
22 209 {
23 210 if (p.MemberInfo is FieldInfo fieldInfo)
@@ -27,22 +214,17 @@ public abstract class XFEProfile
27 214 else
28 215 return null;
29 216 };
30
31 217 /// <summary>
32 218 /// 配置文件清单
33 219 /// </summary>
220 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
34 221 public static List<ProfileInfo> Profiles { get; private set; } = [];
35
36 /// <summary>
37 /// 配置文件所在的默认目录
38 /// </summary>
39 public static string ProfilesDefaultPath { get; set; } = $"{AppDomain.CurrentDomain.BaseDirectory}/Profiles";
40
41 222 /// <summary>
42 223 /// 加载配置文件
43 224 /// </summary>
44 225 /// <param name="profileInfo">配置文件信息</param>
45 226 /// <returns></returns>
227 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
46 228 public static void LoadProfiles(params ProfileInfo[] profileInfo)
47 229 {
48 230 Profiles.AddRange(profileInfo);
@@ -87,6 +269,7 @@ public abstract class XFEProfile
87 269 /// </summary>
88 270 /// <param name="profileInfo">配置文件信息</param>
89 271 /// <returns></returns>
272 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
90 273 public static async Task LoadProfilesAsync(params ProfileInfo[] profileInfo) => await Task.Run(() => LoadProfiles(profileInfo));
91 274
92 275 /// <summary>
@@ -94,6 +277,7 @@ public abstract class XFEProfile
94 277 /// </summary>
95 278 /// <param name="profileInfo">配置文件</param>
96 279 /// <returns></returns>
280 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
97 281 public static void SaveProfile(ProfileInfo profileInfo)
98 282 {
99 283 var waitSaveProfile = Profiles.Find(x => x.Profile == profileInfo.Profile);
@@ -115,6 +299,7 @@ public abstract class XFEProfile
115 299 /// 储存配置文件
116 300 /// </summary>
117 301 /// <returns></returns>
302 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
118 303 public static void SaveProfiles()
119 304 {
120 305 foreach (var profile in Profiles)
@@ -126,6 +311,7 @@ public abstract class XFEProfile
126 311 /// </summary>
127 312 /// <param name="profileInfo">配置文件</param>
128 313 /// <returns></returns>
314 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
129 315 public static async Task SaveProfileAsync(ProfileInfo profileInfo)
130 316 {
131 317 var waitSaveProfile = Profiles.Find(x => x.Profile == profileInfo.Profile);
@@ -145,6 +331,7 @@ public abstract class XFEProfile
145 331 /// 储存配置文件
146 332 /// </summary>
147 333 /// <returns></returns>
334 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
148 335 public static async Task SaveProfilesAsync()
149 336 {
150 337 foreach (var profile in Profiles)
@@ -155,6 +342,7 @@ public abstract class XFEProfile
155 342 /// 删除指定的配置文件
156 343 /// </summary>
157 344 /// <param name="profileInfo">指定的配置文件</param>
345 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
158 346 public static void DeleteProfile(ProfileInfo profileInfo)
159 347 {
160 348 var waitSaveProfile = Profiles.Find(x => x.Profile == profileInfo.Profile);
@@ -169,6 +357,7 @@ public abstract class XFEProfile
169 357 /// </summary>
170 358 /// <param name="profileInfo">指定的配置文件</param>
171 359 /// <returns></returns>
360 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
172 361 public static async Task DeleteProfileAsync(ProfileInfo profileInfo)
173 362 {
174 363 await Task.Run(() =>
@@ -184,6 +373,7 @@ public abstract class XFEProfile
184 373 /// <summary>
185 374 /// 删除所有配置文件
186 375 /// </summary>
376 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
187 377 public static void DeleteProfiles()
188 378 {
189 379 foreach (var profile in Profiles)
@@ -194,6 +384,7 @@ public abstract class XFEProfile
194 384 /// 删除所有配置文件
195 385 /// </summary>
196 386 /// <returns></returns>
387 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
197 388 public static async Task DeleteProfilesAsync()
198 389 {
199 390 foreach (var profile in Profiles)
@@ -204,12 +395,14 @@ public abstract class XFEProfile
204 395 /// 设置储存配置文件的方法
205 396 /// </summary>
206 397 /// <param name="saveProfilesFunc">储存方法</param>
398 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
207 399 public static void SetSaveProfilesFunction(Func<object?, ProfileEntryInfo, string> saveProfilesFunc) => SaveProfilesFunc = saveProfilesFunc;
208 400
209 401 /// <summary>
210 402 /// 设置加载配置文件的方法
211 403 /// </summary>
212 404 /// <param name="loadProfilesFunc">加载方法</param>
405 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
213 406 public static void SetLoadProfilesFunction(Func<string, ProfileEntryInfo, object?> loadProfilesFunc) => LoadProfilesFunc = loadProfilesFunc;
214 407
215 408 /// <summary>
@@ -217,6 +410,7 @@ public abstract class XFEProfile
217 410 /// </summary>
218 411 /// <param name="profileInfo"></param>
219 412 /// <returns></returns>
413 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
220 414 protected static void AutoSave(ProfileInfo profileInfo) => SaveProfile(profileInfo);
221 415
222 416 /// <summary>
@@ -224,6 +418,7 @@ public abstract class XFEProfile
224 418 /// </summary>
225 419 /// <param name="profileInfo"></param>
226 420 /// <returns></returns>
421 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
227 422 protected static async Task AutoSaveAsync(ProfileInfo profileInfo) => await SaveProfileAsync(profileInfo);
228 423
229 424 /// <summary>
@@ -231,6 +426,7 @@ public abstract class XFEProfile
231 426 /// </summary>
232 427 /// <param name="profileInfo">指定的配置文件</param>
233 428 /// <returns></returns>
429 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
234 430 public static string ExportProfile(ProfileInfo profileInfo)
235 431 {
236 432 var waitSaveProfile = Profiles.Find(x => x.Profile == profileInfo.Profile);
@@ -247,6 +443,7 @@ public abstract class XFEProfile
247 443 /// 导出所有配置文件
248 444 /// </summary>
249 445 /// <returns></returns>
446 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
250 447 public static string ExportProfiles()
251 448 {
252 449 var exportProfiles = new XFEDictionary();
@@ -263,6 +460,7 @@ public abstract class XFEProfile
263 460 /// <param name="profileInfo">指定的配置文件</param>
264 461 /// <param name="profileString">配置文件字符串</param>
265 462 /// <param name="autoSave">导入后是否自动储存</param>
463 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
266 464 public static void ImportProfile(ProfileInfo profileInfo, string profileString, bool autoSave = true)
267 465 {
268 466 var instance = profileInfo.GetProfileInstance();
@@ -291,6 +489,7 @@ public abstract class XFEProfile
291 489 /// </summary>
292 490 /// <param name="profileString">配置文件字符串</param>
293 491 /// <param name="autoSave">导入后是否自动储存</param>
492 [Obsolete("XFEProfile现在不再对配置文件实行统一的管理,请对每个配置文件单独操作")]
294 493 public static void ImportProfiles(string profileString, bool autoSave = true)
295 494 {
296 495 var importProfiles = new XFEDictionary(profileString);
@@ -300,4 +499,31 @@ public abstract class XFEProfile
300 499 ImportProfile(profile, importProfiles[profile.Profile.Name]!, autoSave);
301 500 }
302 501 }
502 #endregion
303 503 }
504 /// <summary>
505 /// 配置文件保存方法
506 /// </summary>
507 /// <param name="profileInstance">配置文件实例</param>
508 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
509 /// <param name="propertyGetFuncDictionary">配置文件 “属性名称-属性值获取方法” 字典</param>
510 /// <returns>保存内容</returns>
511 public delegate string ProfileSaveOperation(XFEProfile profileInstance, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, GetValueDelegate> propertyGetFuncDictionary);
512 /// <summary>
513 /// 配置文件加载方法
514 /// </summary>
515 /// <param name="profileInstance">配置文件实例</param>
516 /// <param name="profileString">配置文件字符串</param>
517 /// <param name="propertyInfoDictionary">配置文件 “属性名称-属性类型” 字典</param>
518 /// <param name="propertySetFuncDictionary">配置文件 “属性名称-属性设置方法” 字典</param>
519 public delegate XFEProfile ProfileLoadOperation(XFEProfile profileInstance, string profileString, Dictionary<string, Type> propertyInfoDictionary, Dictionary<string, SetValueDelegate> propertySetFuncDictionary);
520 /// <summary>
521 /// 设置配置文件属性值委托
522 /// </summary>
523 /// <param name="value">要设置的值</param>
524 public delegate void SetValueDelegate(object? value);
525 /// <summary>
526 /// 获取配置文件属性值委托
527 /// </summary>
528 /// <returns>获取的属性值</returns>
529 public delegate object? GetValueDelegate();