返回提交历史
Modified
AutoConfig.Analyzer.Test/Program.cs
+31
-16
Modified
AutoConfig.Analyzer.Test/SystemProfile.cs
+3
-1
Modified
AutoConfig.Analyzer.Test/UserInfo.cs
+1
-1
Modified
AutoConfig.Analyzer.Test/UserProfile.cs
+2
-2
Added
ProfileOperationMode.cs
+0
-0
Modified
XFEExtension.NetCore.AutoConfig.Analyzer/Generator/ProfilePropertyAutoGenerator.cs
+87
-63
Modified
XFEExtension.NetCore.AutoConfig/ProfileList.cs
+1
-1
Added
XFEExtension.NetCore.AutoConfig/ProfileOperationMode.cs
+24
-0
Modified
XFEExtension.NetCore.AutoConfig/XFEProfile.cs
+233
-7
XFEstudio/XFEExtension.NetCore.AutoConfig
初步完成脱离反射的配置文件自动存储
39078ea
代码差异
9 个文件
+382
-91
@@ -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
}
@@ -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
}
@@ -1,4 +1,4 @@
1
namespace PDDShopManagementSystem.ServerConsole;
1
namespace AutoConfig.Analyzer.Test;
2
2
3
3
/// <summary>
4
4
/// 用户信息
@@ -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
/// 用户信息列表
此文件没有可显示的逐行差异。
@@ -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;
@@ -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
@@ -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
}
@@ -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();