Skip to content

Commit fd6ab1e

Browse files
committed
refactor: macOS GUI 消除反射,使用新格式系统显式注册
- 新增 Adapters 目录(FormatRegistrar, NewFormatImporterAdapter, NewFormatExporterAdapter) 将新 IFormatImporter/IFormatExporter 适配为旧 IWordLibraryImport/IWordLibraryExport 接口 - LoadImeList() 替换 Assembly 反射为 GuiFormatRegistrar.RegisterAllForGui() - ImeWlConverterMac.csproj 添加 Abstractions、Formats 项目引用和 DI 包引用 - CodeType 枚举补全 Yong、InnerCode、UserDefinePhrase、Unknown - Formats.csproj 更新 DI 包版本 9.0.0→10.0.7,移除多余 System.Text.Encoding.CodePages,添加 SharpZipLib
1 parent e1fa151 commit fd6ab1e

7 files changed

Lines changed: 328 additions & 43 deletions

File tree

src/ImeWlConverter.Abstractions/Enums/CodeType.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,17 @@ public enum CodeType
5757
Phrase,
5858

5959
/// <summary>Shuangpin (双拼) encoding.</summary>
60-
Shuangpin
60+
Shuangpin,
61+
62+
/// <summary>Yong (永码) encoding.</summary>
63+
Yong,
64+
65+
/// <summary>Internal code encoding.</summary>
66+
InnerCode,
67+
68+
/// <summary>User-defined phrase encoding.</summary>
69+
UserDefinePhrase,
70+
71+
/// <summary>Unknown encoding type.</summary>
72+
Unknown
6173
}

src/ImeWlConverter.Formats/ImeWlConverter.Formats.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
ReferenceOutputAssembly="false"/>
1616
</ItemGroup>
1717
<ItemGroup>
18-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0"/>
19-
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.0"/>
18+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.7"/>
19+
<PackageReference Include="SharpZipLib" Version="1.4.2"/>
2020
</ItemGroup>
2121
</Project>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using ImeWlConverter.Abstractions.Contracts;
4+
using ImeWlConverter.Formats;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Studyzy.IMEWLConverter;
7+
8+
namespace ImeWlConverterMac.Adapters;
9+
10+
/// <summary>
11+
/// Registers all known IME formats using the new format system and wraps them
12+
/// in legacy interface adapters for GUI compatibility.
13+
/// </summary>
14+
public static class FormatRegistrar
15+
{
16+
/// <summary>
17+
/// Registers all formats keyed by display name with sort index for GUI usage.
18+
/// Returns legacy interface dictionaries compatible with MainBody.
19+
/// </summary>
20+
public static (Dictionary<string, IWordLibraryImport> imports, Dictionary<string, IWordLibraryExport> exports, List<string> sortedImportNames, List<string> sortedExportNames)
21+
RegisterAllForGui()
22+
{
23+
var services = new ServiceCollection();
24+
services.AddAllFormats();
25+
var sp = services.BuildServiceProvider();
26+
27+
var importers = sp.GetServices<IFormatImporter>().ToList();
28+
var exporters = sp.GetServices<IFormatExporter>().ToList();
29+
30+
var imports = new Dictionary<string, IWordLibraryImport>();
31+
var exports = new Dictionary<string, IWordLibraryExport>();
32+
var importItems = new List<(string name, int index)>();
33+
var exportItems = new List<(string name, int index)>();
34+
35+
foreach (var importer in importers)
36+
{
37+
var displayName = importer.Metadata.DisplayName;
38+
var adapter = new NewFormatImporterAdapter(importer);
39+
imports[displayName] = adapter;
40+
importItems.Add((displayName, importer.Metadata.SortOrder));
41+
}
42+
43+
foreach (var exporter in exporters)
44+
{
45+
var displayName = exporter.Metadata.DisplayName;
46+
var adapter = new NewFormatExporterAdapter(exporter);
47+
exports[displayName] = adapter;
48+
exportItems.Add((displayName, exporter.Metadata.SortOrder));
49+
}
50+
51+
var sortedImportNames = importItems.OrderBy(x => x.index).Select(x => x.name).ToList();
52+
var sortedExportNames = exportItems.OrderBy(x => x.index).Select(x => x.name).ToList();
53+
54+
return (imports, exports, sortedImportNames, sortedExportNames);
55+
}
56+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using ImeWlConverter.Abstractions.Contracts;
7+
using ImeWlConverter.Abstractions.Models;
8+
using Studyzy.IMEWLConverter;
9+
using Studyzy.IMEWLConverter.Entities;
10+
using OldCodeType = Studyzy.IMEWLConverter.Entities.CodeType;
11+
using NewCodeType = ImeWlConverter.Abstractions.Enums.CodeType;
12+
13+
namespace ImeWlConverterMac.Adapters;
14+
15+
/// <summary>
16+
/// Adapts new IFormatExporter to legacy IWordLibraryExport interface for GUI compatibility.
17+
/// </summary>
18+
public sealed class NewFormatExporterAdapter : IWordLibraryExport
19+
{
20+
private readonly IFormatExporter _exporter;
21+
22+
public NewFormatExporterAdapter(IFormatExporter exporter)
23+
{
24+
_exporter = exporter;
25+
}
26+
27+
public Encoding Encoding => Encoding.UTF8;
28+
public OldCodeType CodeType => OldCodeType.Pinyin;
29+
30+
public event Action<string>? ExportErrorNotice;
31+
32+
public IList<string> Export(WordLibraryList wlList)
33+
{
34+
var entries = ConvertToWordEntries(wlList);
35+
36+
using var ms = new MemoryStream();
37+
_exporter.ExportAsync(entries, ms).GetAwaiter().GetResult();
38+
ms.Position = 0;
39+
40+
using var reader = new StreamReader(ms, Encoding.UTF8);
41+
var content = reader.ReadToEnd();
42+
43+
return new List<string> { content };
44+
}
45+
46+
public string ExportLine(WordLibrary wl)
47+
{
48+
var entry = ConvertToWordEntry(wl);
49+
if (entry == null) return string.Empty;
50+
51+
var entries = new List<WordEntry> { entry };
52+
using var ms = new MemoryStream();
53+
_exporter.ExportAsync(entries, ms).GetAwaiter().GetResult();
54+
ms.Position = 0;
55+
56+
using var reader = new StreamReader(ms, Encoding.UTF8);
57+
return reader.ReadToEnd().TrimEnd('\r', '\n');
58+
}
59+
60+
private static List<WordEntry> ConvertToWordEntries(WordLibraryList wlList)
61+
{
62+
var entries = new List<WordEntry>(wlList.Count);
63+
foreach (var wl in wlList)
64+
{
65+
var entry = ConvertToWordEntry(wl);
66+
if (entry != null)
67+
entries.Add(entry);
68+
}
69+
return entries;
70+
}
71+
72+
private static WordEntry? ConvertToWordEntry(WordLibrary wl)
73+
{
74+
if (string.IsNullOrEmpty(wl.Word))
75+
return null;
76+
77+
WordCode? code = null;
78+
if (wl.Codes != null && wl.Codes.Count > 0)
79+
{
80+
var segments = new List<IReadOnlyList<string>>(wl.Codes.Count);
81+
foreach (var segment in wl.Codes)
82+
{
83+
segments.Add(segment.ToList());
84+
}
85+
code = new WordCode { Segments = segments };
86+
}
87+
88+
return new WordEntry
89+
{
90+
Word = wl.Word,
91+
Rank = wl.Rank,
92+
IsEnglish = wl.IsEnglish,
93+
CodeType = MapOldCodeTypeToNew(wl.CodeType),
94+
Code = code
95+
};
96+
}
97+
98+
private static NewCodeType MapOldCodeTypeToNew(OldCodeType old) => old switch
99+
{
100+
OldCodeType.Pinyin => NewCodeType.Pinyin,
101+
OldCodeType.Wubi => NewCodeType.Wubi86,
102+
OldCodeType.Wubi98 => NewCodeType.Wubi98,
103+
OldCodeType.WubiNewAge => NewCodeType.WubiNewAge,
104+
OldCodeType.Zhengma => NewCodeType.Zhengma,
105+
OldCodeType.Cangjie => NewCodeType.Cangjie5,
106+
OldCodeType.TerraPinyin => NewCodeType.TerraPinyin,
107+
OldCodeType.Zhuyin => NewCodeType.Zhuyin,
108+
OldCodeType.English => NewCodeType.English,
109+
OldCodeType.UserDefine => NewCodeType.UserDefine,
110+
OldCodeType.NoCode => NewCodeType.NoCode,
111+
OldCodeType.QingsongErbi => NewCodeType.QingsongErbi,
112+
OldCodeType.ChaoqiangErbi => NewCodeType.ChaoqiangErbi,
113+
OldCodeType.XiandaiErbi => NewCodeType.XiandaiErbi,
114+
OldCodeType.ChaoqingYinxin => NewCodeType.YinxingErbi,
115+
OldCodeType.Chaoyin => NewCodeType.Chaoyin,
116+
OldCodeType.Yong => NewCodeType.Yong,
117+
OldCodeType.InnerCode => NewCodeType.InnerCode,
118+
OldCodeType.UserDefinePhrase => NewCodeType.UserDefinePhrase,
119+
OldCodeType.Unknown => NewCodeType.Unknown,
120+
_ => NewCodeType.Pinyin
121+
};
122+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using ImeWlConverter.Abstractions.Contracts;
7+
using ImeWlConverter.Abstractions.Models;
8+
using Studyzy.IMEWLConverter;
9+
using Studyzy.IMEWLConverter.Entities;
10+
using OldCodeType = Studyzy.IMEWLConverter.Entities.CodeType;
11+
using NewCodeType = ImeWlConverter.Abstractions.Enums.CodeType;
12+
13+
namespace ImeWlConverterMac.Adapters;
14+
15+
/// <summary>
16+
/// Adapts new IFormatImporter to legacy IWordLibraryImport interface for GUI compatibility.
17+
/// </summary>
18+
public sealed class NewFormatImporterAdapter : IWordLibraryImport
19+
{
20+
private readonly IFormatImporter _importer;
21+
22+
public NewFormatImporterAdapter(IFormatImporter importer)
23+
{
24+
_importer = importer;
25+
}
26+
27+
public int CountWord { get; set; }
28+
public int CurrentStatus { get; set; }
29+
public bool IsText => !_importer.Metadata.IsBinary;
30+
public OldCodeType CodeType => MapCodeType(_importer.Metadata.Id);
31+
32+
public event Action<string>? ImportLineErrorNotice;
33+
34+
public WordLibraryList Import(string path)
35+
{
36+
using var stream = File.OpenRead(path);
37+
var result = _importer.ImportAsync(stream).GetAwaiter().GetResult();
38+
var wlList = new WordLibraryList();
39+
40+
foreach (var entry in result.Entries)
41+
{
42+
var wl = ConvertToWordLibrary(entry);
43+
if (wl != null)
44+
wlList.Add(wl);
45+
}
46+
47+
CountWord = wlList.Count;
48+
return wlList;
49+
}
50+
51+
public WordLibraryList ImportLine(string str)
52+
{
53+
// Not all new importers support line-by-line import; return empty list
54+
return new WordLibraryList();
55+
}
56+
57+
private static WordLibrary? ConvertToWordLibrary(WordEntry entry)
58+
{
59+
if (string.IsNullOrEmpty(entry.Word))
60+
return null;
61+
62+
var wl = new WordLibrary
63+
{
64+
Word = entry.Word,
65+
Rank = entry.Rank,
66+
IsEnglish = entry.IsEnglish,
67+
CodeType = MapNewCodeTypeToOld(entry.CodeType)
68+
};
69+
70+
if (entry.Code != null)
71+
{
72+
var code = new Code();
73+
foreach (var segment in entry.Code.Segments)
74+
{
75+
code.Add(segment.ToList());
76+
}
77+
wl.Codes = code;
78+
}
79+
80+
return wl;
81+
}
82+
83+
private static OldCodeType MapNewCodeTypeToOld(NewCodeType newType) => newType switch
84+
{
85+
NewCodeType.Pinyin => OldCodeType.Pinyin,
86+
NewCodeType.Wubi86 => OldCodeType.Wubi,
87+
NewCodeType.Wubi98 => OldCodeType.Wubi98,
88+
NewCodeType.WubiNewAge => OldCodeType.WubiNewAge,
89+
NewCodeType.Zhengma => OldCodeType.Zhengma,
90+
NewCodeType.Cangjie5 => OldCodeType.Cangjie,
91+
NewCodeType.TerraPinyin => OldCodeType.TerraPinyin,
92+
NewCodeType.Zhuyin => OldCodeType.Zhuyin,
93+
NewCodeType.English => OldCodeType.English,
94+
NewCodeType.UserDefine => OldCodeType.UserDefine,
95+
NewCodeType.NoCode => OldCodeType.NoCode,
96+
NewCodeType.QingsongErbi => OldCodeType.QingsongErbi,
97+
NewCodeType.ChaoqiangErbi => OldCodeType.ChaoqiangErbi,
98+
NewCodeType.XiandaiErbi => OldCodeType.XiandaiErbi,
99+
NewCodeType.YinxingErbi => OldCodeType.ChaoqingYinxin,
100+
NewCodeType.Chaoyin => OldCodeType.Chaoyin,
101+
NewCodeType.Yong => OldCodeType.Yong,
102+
NewCodeType.InnerCode => OldCodeType.InnerCode,
103+
NewCodeType.UserDefinePhrase => OldCodeType.UserDefinePhrase,
104+
NewCodeType.Unknown => OldCodeType.Unknown,
105+
_ => OldCodeType.Pinyin
106+
};
107+
108+
private static OldCodeType MapCodeType(string formatId) => formatId switch
109+
{
110+
"wb86" => OldCodeType.Wubi,
111+
"wb98" => OldCodeType.Wubi98,
112+
"wbnewage" => OldCodeType.WubiNewAge,
113+
"qqwb" => OldCodeType.Wubi,
114+
"xywb" => OldCodeType.Wubi,
115+
"cjpt" => OldCodeType.Cangjie,
116+
"rime" => OldCodeType.Pinyin,
117+
_ => OldCodeType.Pinyin
118+
};
119+
}

src/ImeWlConverterMac/ImeWlConverterMac.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,14 @@
5050
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.3" />
5151
</ItemGroup>
5252

53+
<ItemGroup>
54+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
55+
</ItemGroup>
56+
5357
<ItemGroup>
5458
<ProjectReference Include="../ImeWlConverterCore/ImeWlConverterCore.csproj" />
59+
<ProjectReference Include="../ImeWlConverter.Abstractions/ImeWlConverter.Abstractions.csproj" />
60+
<ProjectReference Include="../ImeWlConverter.Formats/ImeWlConverter.Formats.csproj" />
5561
</ItemGroup>
5662

5763
<ItemGroup>

0 commit comments

Comments
 (0)