XFEExtension
【DLL】XFE各类拓展是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供Xunit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等
关注
0
Fork
0
Star
0
返回提交历史
Modified
XFEExtension.NetCore.Analyzer.Test/SystemProfile.cs
+2
-5
Modified
XFEExtension.NetCore.Analyzer.Test/TestClass.cs
+6
-1
Modified
XFEExtension.NetCore.Analyzer/Generator/ProfilePropertyAutoGenerator.cs
+11
-82
Modified
XFEExtension.NetCore/ProfileExtension/ProfileEntryInfo.cs
+3
-7
Added
XFEExtension.NetCore/ProfileExtension/ProfileFieldAutoGenerateAttribute.cs
+9
-0
Modified
XFEExtension.NetCore/ProfileExtension/ProfileInfo.cs
+6
-5
Modified
XFEExtension.NetCore/ProfileExtension/XFEProfile.cs
+70
-25
XFEstudio/XFEExtension
修复了导入和导出配置文件的bug
b38d426
代码差异
7 个文件
+107
-125
@@ -9,11 +9,8 @@ public static partial class SystemProfile
9
9
/// 名称
10
10
/// </summary>
11
11
[ProfileProperty]
12
[ProfilePropertyAddGet("Console.WriteLine()")]
13
[ProfilePropertyAddGet("Console.WriteLine()")]
14
[ProfilePropertyAddGet($@"return name")]
15
[ProfilePropertyAddSet("Console.WriteLine(value)")]
16
[ProfilePropertyAddSet("name = value")]
12
[ProfilePropertyAddGet(@"Console.WriteLine(""获取了Name"")")]
13
[ProfilePropertyAddGet("return name")]
17
14
private static string name = string.Empty;
18
15
#endregion
19
16
[ProfileProperty]
@@ -1,4 +1,6 @@
1
namespace XFEExtension.NetCore.Analyzer.Test;
1
using XFEExtension.NetCore.ProfileExtension;
2
3
namespace XFEExtension.NetCore.Analyzer.Test;
2
4
3
5
internal class TestClass
4
6
{
@@ -6,5 +8,8 @@ internal class TestClass
6
8
{
7
9
Console.WriteLine(SystemProfile.Name);
8
10
Console.WriteLine(SystemProfile.Age);
11
XFEProfile.ImportProfiles("|{+-[+-SystemProfile-+][+-|{++-[++-name-++][++-\"New Name\"-++]-++}||{++-[++-_age-++][++-33-++]-++}|-+]-+}|");
12
Console.WriteLine(SystemProfile.Name);
13
Console.WriteLine(SystemProfile.Age);
9
14
}
10
15
}
@@ -35,7 +35,7 @@ namespace XFEExtension.NetCore.Analyzer.Generator
35
35
var className = classDeclaration.Identifier.ValueText;
36
36
var attributeSyntax = SyntaxFactory.AttributeList(
37
37
SyntaxFactory.SingletonSeparatedList(
38
SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.ProfileExtension.ProfileProperty"))));
38
SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::XFEExtension.NetCore.ProfileExtension.ProfileFieldAutoGenerateAttribute"))));
39
39
var properties = fieldDeclarationSyntaxes.Select(fieldDeclarationSyntax =>
40
40
{
41
41
var variableDeclaration = fieldDeclarationSyntax.Declaration.Variables.First();
@@ -192,31 +192,19 @@ namespace XFEExtension.NetCore.Analyzer.Generator
192
192
193
193
public static bool IsProfilePropertyAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "ProfileProperty");
194
194
195
public static List<AttributeSyntax> GetProfilePropertyAttributeList(FieldDeclarationSyntax fieldDeclaration)
196
{
197
return fieldDeclaration.AttributeLists.Where(IsProfilePropertyAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
198
}
195
public static List<AttributeSyntax> GetProfilePropertyAttributeList(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsProfilePropertyAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
199
196
200
197
public static bool IsAutoLoadProfileAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "AutoLoadProfile");
201
198
202
public static List<AttributeSyntax> GetAutoLoadProfileAttribute(FieldDeclarationSyntax fieldDeclaration)
203
{
204
return fieldDeclaration.AttributeLists.Where(IsAutoLoadProfileAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
205
}
199
public static List<AttributeSyntax> GetAutoLoadProfileAttribute(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsAutoLoadProfileAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
206
200
207
201
public static bool IsProfilePropertyAddGetAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "ProfilePropertyAddGet");
208
202
209
public static List<AttributeSyntax> GetProfilePropertyAddGetAttributeList(FieldDeclarationSyntax fieldDeclaration)
210
{
211
return fieldDeclaration.AttributeLists.Where(IsProfilePropertyAddGetAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
212
}
203
public static List<AttributeSyntax> GetProfilePropertyAddGetAttributeList(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsProfilePropertyAddGetAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
213
204
214
205
public static bool IsProfilePropertyAddSetAttribute(AttributeListSyntax attributeList) => attributeList.Attributes.Any(attribute => attribute.Name.ToString() == "ProfilePropertyAddSet");
215
206
216
public static List<AttributeSyntax> GetProfilePropertyAddSetAttributeList(FieldDeclarationSyntax fieldDeclaration)
217
{
218
return fieldDeclaration.AttributeLists.Where(IsProfilePropertyAddSetAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
219
}
207
public static List<AttributeSyntax> GetProfilePropertyAddSetAttributeList(FieldDeclarationSyntax fieldDeclaration) => fieldDeclaration.AttributeLists.Where(IsProfilePropertyAddSetAttribute).SelectMany(attributeList => attributeList.Attributes).ToList();
220
208
221
209
public static FileScopedNamespaceDeclarationSyntax GetFileScopedNamespaceDeclaration(SyntaxNode rootNode)
222
210
{
@@ -226,17 +214,13 @@ namespace XFEExtension.NetCore.Analyzer.Generator
226
214
return null;
227
215
}
228
216
229
public static IEnumerable<FieldDeclarationSyntax> GetFieldDeclarations(ClassDeclarationSyntax classDeclaration)
230
{
231
return classDeclaration.DescendantNodes().OfType<FieldDeclarationSyntax>()
232
.Where(fieldDeclarationSyntax => fieldDeclarationSyntax.AttributeLists.Any(IsProfilePropertyAttribute) && fieldDeclarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword));
233
}
217
public static IEnumerable<FieldDeclarationSyntax> GetFieldDeclarations(ClassDeclarationSyntax classDeclaration) => classDeclaration.DescendantNodes()
218
.OfType<FieldDeclarationSyntax>()
219
.Where(fieldDeclarationSyntax => fieldDeclarationSyntax.AttributeLists.Any(IsProfilePropertyAttribute) && fieldDeclarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword));
234
220
235
public static IEnumerable<ClassDeclarationSyntax> GetClassDeclarations(SyntaxNode rootNode)
236
{
237
return rootNode.DescendantNodes().OfType<ClassDeclarationSyntax>()
238
.Where(classDeclaration => classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword));
239
}
221
public static IEnumerable<ClassDeclarationSyntax> GetClassDeclarations(SyntaxNode rootNode) => rootNode.DescendantNodes()
222
.OfType<ClassDeclarationSyntax>()
223
.Where(classDeclaration => classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword));
240
224
241
225
private static SyntaxTree GenerateProfileClassSyntaxTree(ClassDeclarationSyntax classDeclaration, UsingDirectiveSyntax[] usingDirectiveSyntaxes, IEnumerable<PropertyDeclarationSyntax> propertyDeclarationSyntaxes, FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDeclarationSyntax)
242
226
{
@@ -298,60 +282,5 @@ namespace XFEExtension.NetCore.Analyzer.Generator
298
282
.NormalizeWhitespace();
299
283
return SyntaxFactory.SyntaxTree(profileClassCompilationUnit);
300
284
}
301
// 定义Windows API
302
[DllImport("user32.dll")]
303
[return: MarshalAs(UnmanagedType.Bool)]
304
public static extern bool OpenClipboard(IntPtr hWndNewOwner);
305
306
[DllImport("user32.dll")]
307
[return: MarshalAs(UnmanagedType.Bool)]
308
public static extern bool EmptyClipboard();
309
310
[DllImport("user32.dll")]
311
public static extern IntPtr SetClipboardData(uint uFormat, IntPtr data);
312
313
[DllImport("user32.dll")]
314
[return: MarshalAs(UnmanagedType.Bool)]
315
public static extern bool CloseClipboard();
316
317
[DllImport("kernel32.dll", SetLastError = true)]
318
public static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
319
320
[DllImport("kernel32.dll", SetLastError = true)]
321
public static extern IntPtr GlobalLock(IntPtr hMem);
322
323
[DllImport("kernel32.dll", SetLastError = true)]
324
[return: MarshalAs(UnmanagedType.Bool)]
325
public static extern bool GlobalUnlock(IntPtr hMem);
326
public static bool SetClipboardText(string text)
327
{
328
// 打开剪切板
329
if (!OpenClipboard(IntPtr.Zero))
330
return false;
331
332
// 清空剪切板
333
EmptyClipboard();
334
335
// 分配内存
336
IntPtr hGlobal = GlobalAlloc(0x2000, (UIntPtr)((text.Length + 1) * 2)); // 0x2000 是GMEM_MOVEABLE
337
338
// 锁定内存
339
IntPtr pGlobal = GlobalLock(hGlobal);
340
341
// 将文本复制到内存
342
byte[] bytes = Encoding.Unicode.GetBytes(text);
343
Marshal.Copy(bytes, 0, pGlobal, bytes.Length);
344
345
// 解锁内存
346
GlobalUnlock(hGlobal);
347
348
// 将内存设置到剪切板
349
SetClipboardData(13, hGlobal);
350
351
// 关闭剪切板
352
CloseClipboard();
353
354
return true;
355
}
356
285
}
357
286
}
@@ -6,19 +6,15 @@ namespace XFEExtension.NetCore.ProfileExtension;
6
6
/// 配置文件属性信息
7
7
/// </summary>
8
8
/// <param name="name">属性名称</param>
9
/// <param name="propertyInfo">属性信息</param>
10
public class ProfileEntryInfo(string name, PropertyInfo propertyInfo)
9
/// <param name="memberInfo">属性信息</param>
10
public class ProfileEntryInfo(string name, MemberInfo memberInfo)
11
11
{
12
12
/// <summary>
13
13
/// 属性名称
14
14
/// </summary>
15
15
public string Name { get; set; } = name;
16
16
/// <summary>
17
/// 属性值
18
/// </summary>
19
public string? Value { get { return Property.GetValue(null)?.ToString(); } }
20
/// <summary>
21
17
/// 属性信息
22
18
/// </summary>
23
public PropertyInfo Property { get; init; } = propertyInfo;
19
public MemberInfo MemberInfo { get; init; } = memberInfo;
24
20
}
@@ -0,0 +1,9 @@
1
namespace XFEExtension.NetCore.ProfileExtension;
2
3
/// <summary>
4
/// 将属性添加至储存列表
5
/// </summary>
6
[AttributeUsage(AttributeTargets.Property)]
7
public class ProfileFieldAutoGenerateAttribute : Attribute
8
{
9
}
@@ -25,13 +25,14 @@ public class ProfileInfo(Type profileType, string path = "", string description
25
25
/// <summary>
26
26
/// 配置文件属性列表
27
27
/// </summary>
28
public List<ProfileEntryInfo> PropertiesInfo { get; init; } = GetPropertiesWithProfileAttribute(profileType);
29
internal static List<ProfileEntryInfo> GetPropertiesWithProfileAttribute(Type type)
28
public List<ProfileEntryInfo> MemberInfo { get; init; } = GetMemberWithProfileAttribute(profileType);
29
internal static List<ProfileEntryInfo> GetMemberWithProfileAttribute(Type type)
30
30
{
31
31
var profileEntryList = new List<ProfileEntryInfo>();
32
foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
33
if (propertyInfo.GetCustomAttribute<ProfilePropertyAttribute>() is not null)
34
profileEntryList.Add(new ProfileEntryInfo(propertyInfo.Name, propertyInfo));
32
foreach (var memberInfo in type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
33
if (memberInfo is not MethodInfo)
34
if (memberInfo.GetCustomAttribute<ProfilePropertyAttribute>() is not null)
35
profileEntryList.Add(new ProfileEntryInfo(memberInfo.Name, memberInfo));
35
36
return profileEntryList;
36
37
}
37
38
/// <summary>
@@ -1,4 +1,5 @@
1
using System.Text.Json;
1
using System.Reflection;
2
using System.Text.Json;
2
3
using XFEExtension.NetCore.FormatExtension;
3
4
4
5
namespace XFEExtension.NetCore.ProfileExtension;
@@ -8,8 +9,24 @@ namespace XFEExtension.NetCore.ProfileExtension;
8
9
/// </summary>
9
10
public abstract class XFEProfile
10
11
{
11
private static Func<ProfileEntryInfo, string> SaveProfilesFunc { get; set; } = p => JsonSerializer.Serialize(p.Property.GetValue(null));
12
private static Func<string, ProfileEntryInfo, object?> LoadProfilesFunc { get; set; } = (x, p) => JsonSerializer.Deserialize(x, p.Property.PropertyType);
12
private static Func<ProfileEntryInfo, string> SaveProfilesFunc { get; set; } = p =>
13
{
14
if (p.MemberInfo is FieldInfo fieldInfo)
15
return JsonSerializer.Serialize(fieldInfo.GetValue(null));
16
else if (p.MemberInfo is PropertyInfo propertyInfo)
17
return JsonSerializer.Serialize(propertyInfo.GetValue(null));
18
else
19
return string.Empty;
20
};
21
private static Func<string, ProfileEntryInfo, object?> LoadProfilesFunc { get; set; } = (x, p) =>
22
{
23
if (p.MemberInfo is FieldInfo fieldInfo)
24
return JsonSerializer.Deserialize(x, fieldInfo.FieldType);
25
else if (p.MemberInfo is PropertyInfo propertyInfo)
26
return JsonSerializer.Deserialize(x, propertyInfo.PropertyType);
27
else
28
return null;
29
};
13
30
14
31
/// <summary>
15
32
/// 配置文件清单
@@ -34,22 +51,28 @@ public abstract class XFEProfile
34
51
if (!File.Exists(profile.Path))
35
52
continue;
36
53
XFEDictionary propertyFileContent = File.ReadAllText(profile.Path);
37
for (int i = 0; i < profile.PropertiesInfo.Count; i++)
54
for (int i = 0; i < profile.MemberInfo.Count; i++)
38
55
{
39
56
for (int j = 0; j < propertyFileContent.Count; j++)
40
57
{
41
var propertyInfo = profile.PropertiesInfo[i];
58
var memberInfo = profile.MemberInfo[i];
42
59
var property = propertyFileContent.ElementAt(j);
43
if (property.Header == propertyInfo.Name)
60
if (property.Header == memberInfo.Name)
44
61
{
45
profile.PropertiesInfo[i].Property.SetValue(null, LoadProfilesFunc(property.Content, propertyInfo));
62
if (memberInfo.MemberInfo is FieldInfo fieldInfo)
63
fieldInfo.SetValue(null, LoadProfilesFunc(property.Content, memberInfo));
64
else if (memberInfo.MemberInfo is PropertyInfo propertyInfo)
65
propertyInfo.SetValue(null, LoadProfilesFunc(property.Content, memberInfo));
46
66
continue;
47
67
}
48
68
foreach (var propertySecFind in propertyFileContent)
49
69
{
50
if (propertySecFind.Header == propertyInfo.Name)
70
if (propertySecFind.Header == memberInfo.Name)
51
71
{
52
profile.PropertiesInfo[i].Property.SetValue(null, LoadProfilesFunc(propertySecFind.Content, propertyInfo));
72
if (profile.MemberInfo[i].MemberInfo is FieldInfo fieldInfo)
73
fieldInfo.SetValue(null, LoadProfilesFunc(propertySecFind.Content, memberInfo));
74
else if (profile.MemberInfo[i].MemberInfo is PropertyInfo propertyInfo)
75
propertyInfo.SetValue(null, LoadProfilesFunc(propertySecFind.Content, memberInfo));
53
76
break;
54
77
}
55
78
}
@@ -76,7 +99,7 @@ public abstract class XFEProfile
76
99
if (waitSaveProfile is null)
77
100
return;
78
101
var saveProfileDictionary = new XFEDictionary();
79
foreach (var property in waitSaveProfile.PropertiesInfo)
102
foreach (var property in waitSaveProfile.MemberInfo)
80
103
saveProfileDictionary.Add(property.Name, SaveProfilesFunc(property));
81
104
var fileSavePath = Path.GetDirectoryName(waitSaveProfile.Path);
82
105
if (!Directory.Exists(fileSavePath) && fileSavePath is not null && fileSavePath != string.Empty)
@@ -105,7 +128,7 @@ public abstract class XFEProfile
105
128
if (waitSaveProfile is null)
106
129
return;
107
130
var saveProfileDictionary = new XFEDictionary();
108
foreach (var property in waitSaveProfile.PropertiesInfo)
131
foreach (var property in waitSaveProfile.MemberInfo)
109
132
saveProfileDictionary.Add(property.Name, SaveProfilesFunc(property));
110
133
var fileSavePath = Path.GetDirectoryName(waitSaveProfile.Path);
111
134
if (!Directory.Exists(fileSavePath) && fileSavePath is not null && fileSavePath != string.Empty)
@@ -160,7 +183,7 @@ public abstract class XFEProfile
160
183
if (waitSaveProfile is null)
161
184
return string.Empty;
162
185
var saveProfileDictionary = new XFEDictionary();
163
foreach (var property in waitSaveProfile.PropertiesInfo)
186
foreach (var property in waitSaveProfile.MemberInfo)
164
187
saveProfileDictionary.Add(property.Name, SaveProfilesFunc(property));
165
188
return saveProfileDictionary.ToString();
166
189
}
@@ -178,25 +201,47 @@ public abstract class XFEProfile
178
201
}
179
202
180
203
/// <summary>
181
/// 导入配置文件
204
/// 导入指定的配置文件<br/>
205
/// 本方法仅支持导入由<seealso cref="ExportProfile(ProfileInfo)"/>导出的配置文件<br/><br/>
206
/// 如需导入由<seealso cref="ExportProfiles"/>导出的配置文件,请使用<seealso cref="ImportProfiles(string,bool)"/>
182
207
/// </summary>
208
/// <param name="profileInfo">指定的配置文件</param>
183
209
/// <param name="profileString">配置文件字符串</param>
184
public static void ImportProfile(string profileString)
210
/// <param name="autoSave">导入后是否自动储存</param>
211
public static void ImportProfile(ProfileInfo profileInfo, string profileString, bool autoSave = true)
185
212
{
186
var importProfile = new XFEDictionary(profileString);
187
foreach (var profile in Profiles)
213
var waitSaveProfile = Profiles.Find(x => x.Profile == profileInfo.Profile);
214
if (waitSaveProfile is null)
215
return;
216
var importProfileDictionary = new XFEDictionary(profileString);
217
foreach (var property in waitSaveProfile.MemberInfo)
188
218
{
189
if (importProfile[profile.Profile.Name] is not null)
219
if (importProfileDictionary[property.Name] is not null)
190
220
{
191
var profileContent = importProfile[profile.Profile.Name];
192
var profileContentDictionary = new XFEDictionary(profileContent!);
193
for (int i = 0; i < profile.PropertiesInfo.Count; i++)
194
{
195
var propertyInfo = profile.PropertiesInfo[i];
196
if (profileContentDictionary[propertyInfo.Name] is not null)
197
profile.PropertiesInfo[i].Property.SetValue(null, LoadProfilesFunc(profileContentDictionary[propertyInfo.Name]!, propertyInfo));
198
}
221
if (property.MemberInfo is FieldInfo fieldInfo)
222
fieldInfo.SetValue(null, LoadProfilesFunc(importProfileDictionary[property.Name]!, property));
223
else if (property.MemberInfo is PropertyInfo propertyInfo)
224
propertyInfo.SetValue(null, LoadProfilesFunc(importProfileDictionary[property.Name]!, property));
199
225
}
200
226
}
227
if (autoSave)
228
SaveProfile(profileInfo);
229
}
230
231
/// <summary>
232
/// 导入所有配置文件<br/>
233
/// 本方法仅支持导入由<seealso cref="ExportProfiles"/>导出的配置文件<br/><br/>
234
/// 如需导入由<seealso cref="ExportProfile(ProfileInfo)"/>导出的配置文件,请使用<seealso cref="ImportProfile(ProfileInfo, string,bool)"/>
235
/// </summary>
236
/// <param name="profileString">配置文件字符串</param>
237
/// <param name="autoSave">导入后是否自动储存</param>
238
public static void ImportProfiles(string profileString, bool autoSave = true)
239
{
240
var importProfiles = new XFEDictionary(profileString);
241
foreach (var profile in Profiles)
242
{
243
if (importProfiles[profile.Profile.Name] is not null)
244
ImportProfile(profile, importProfiles[profile.Profile.Name]!, autoSave);
245
}
201
246
}
202
247
}