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

XFEExtension

【DLL】XFE各类拓展是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供Xunit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等

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

XFEstudio/XFEExtension

修复了导入和导出配置文件的bug

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

代码差异

7 个文件 +107 -125
Modified XFEExtension.NetCore.Analyzer.Test/SystemProfile.cs +2 -5
@@ -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]
Modified XFEExtension.NetCore.Analyzer.Test/TestClass.cs +6 -1
@@ -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 }
Modified XFEExtension.NetCore.Analyzer/Generator/ProfilePropertyAutoGenerator.cs +11 -82
@@ -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 }
Modified XFEExtension.NetCore/ProfileExtension/ProfileEntryInfo.cs +3 -7
@@ -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 }
Added XFEExtension.NetCore/ProfileExtension/ProfileFieldAutoGenerateAttribute.cs +9 -0
@@ -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 }
Modified XFEExtension.NetCore/ProfileExtension/ProfileInfo.cs +6 -5
@@ -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>
Modified XFEExtension.NetCore/ProfileExtension/XFEProfile.cs +70 -25
@@ -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 }