Skip to content

Commit 048fa3d

Browse files
committed
refactor(localization): 重构资源提供者实现以提高性能和可维护性
- 将 ILazyResourceProvider 拆分为单独文件 - 使用 ConcurrentDictionary 优化程序集资源提供者管理 - 简化资源管理器查找逻辑,移除不必要的分类处理 - 改进资源加载的线程安全性和错误处理
1 parent b1ce192 commit 048fa3d

4 files changed

Lines changed: 136 additions & 116 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// ==========================================================================================
2+
// GameFrameX 组织及其衍生项目的版权、商标、专利及其他相关权利
3+
// GameFrameX organization and its derivative projects' copyrights, trademarks, patents, and related rights
4+
// 均受中华人民共和国及相关国际法律法规保护。
5+
// are protected by the laws of the People's Republic of China and relevant international regulations.
6+
//
7+
// 使用本项目须严格遵守相应法律法规及开源许可证之规定。
8+
// Usage of this project must strictly comply with applicable laws, regulations, and open-source licenses.
9+
//
10+
// 本项目采用 MIT 许可证与 Apache License 2.0 双许可证分发,
11+
// This project is dual-licensed under the MIT License and Apache License 2.0,
12+
// 完整许可证文本请参见源代码根目录下的 LICENSE 文件。
13+
// please refer to the LICENSE file in the root directory of the source code for the full license text.
14+
//
15+
// 禁止利用本项目实施任何危害国家安全、破坏社会秩序、
16+
// It is prohibited to use this project to engage in any activities that endanger national security, disrupt social order,
17+
// 侵犯他人合法权益等法律法规所禁止的行为!
18+
// or infringe upon the legitimate rights and interests of others, as prohibited by laws and regulations!
19+
// 因基于本项目二次开发所产生的一切法律纠纷与责任,
20+
// Any legal disputes and liabilities arising from secondary development based on this project
21+
// 本项目组织与贡献者概不承担。
22+
// shall be borne solely by the developer; the project organization and contributors assume no responsibility.
23+
//
24+
// GitHub 仓库:https://github.com/GameFrameX
25+
// GitHub Repository: https://github.com/GameFrameX
26+
// Gitee 仓库:https://gitee.com/GameFrameX
27+
// Gitee Repository: https://gitee.com/GameFrameX
28+
// 官方文档:https://gameframex.doc.alianblank.com/
29+
// Official Documentation: https://gameframex.doc.alianblank.com/
30+
// ==========================================================================================
31+
32+
namespace GameFrameX.Foundation.Localization.Core;
33+
34+
/// <summary>
35+
/// 可懒加载的资源提供者接口
36+
/// </summary>
37+
/// <remarks>
38+
/// 继承自 IResourceProvider,增加了懒加载能力,支持资源的延迟初始化。
39+
/// 实现者可以优化资源加载性能,只在需要时才加载资源。
40+
/// </remarks>
41+
public interface ILazyResourceProvider : IResourceProvider
42+
{
43+
/// <summary>
44+
/// 获取一个值,指示资源提供者是否已完成初始化
45+
/// </summary>
46+
/// <value>
47+
/// 如果资源提供者已加载并准备好提供服务,则为 true;否则为 false。
48+
/// </value>
49+
bool IsInitialized { get; }
50+
51+
/// <summary>
52+
/// 确保资源已加载并初始化
53+
/// </summary>
54+
/// <remarks>
55+
/// 如果资源尚未加载,此方法将触发资源加载过程。
56+
/// 如果资源已经加载,此方法应该立即返回,不执行额外操作。
57+
/// 实现者应该确保此方法是线程安全的,可以多次调用。
58+
/// </remarks>
59+
/// <example>
60+
/// <code>
61+
/// var provider = new MyLazyResourceProvider();
62+
/// Console.WriteLine($"Initialized: {provider.IsInitialized}"); // false
63+
///
64+
/// provider.EnsureLoaded();
65+
/// Console.WriteLine($"Initialized: {provider.IsInitialized}"); // true
66+
///
67+
/// provider.EnsureLoaded(); // 重复调用应该快速返回
68+
/// </code>
69+
/// </example>
70+
void EnsureLoaded();
71+
}

GameFrameX.Foundation.Localization/Core/IResourceProvider.cs

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -35,43 +35,4 @@ public interface IResourceProvider
3535
/// </code>
3636
/// </example>
3737
string GetString(string key);
38-
}
39-
40-
/// <summary>
41-
/// 可懒加载的资源提供者接口
42-
/// </summary>
43-
/// <remarks>
44-
/// 继承自 IResourceProvider,增加了懒加载能力,支持资源的延迟初始化。
45-
/// 实现者可以优化资源加载性能,只在需要时才加载资源。
46-
/// </remarks>
47-
public interface ILazyResourceProvider : IResourceProvider
48-
{
49-
/// <summary>
50-
/// 获取一个值,指示资源提供者是否已完成初始化
51-
/// </summary>
52-
/// <value>
53-
/// 如果资源提供者已加载并准备好提供服务,则为 true;否则为 false。
54-
/// </value>
55-
bool IsInitialized { get; }
56-
57-
/// <summary>
58-
/// 确保资源已加载并初始化
59-
/// </summary>
60-
/// <remarks>
61-
/// 如果资源尚未加载,此方法将触发资源加载过程。
62-
/// 如果资源已经加载,此方法应该立即返回,不执行额外操作。
63-
/// 实现者应该确保此方法是线程安全的,可以多次调用。
64-
/// </remarks>
65-
/// <example>
66-
/// <code>
67-
/// var provider = new MyLazyResourceProvider();
68-
/// Console.WriteLine($"Initialized: {provider.IsInitialized}"); // false
69-
///
70-
/// provider.EnsureLoaded();
71-
/// Console.WriteLine($"Initialized: {provider.IsInitialized}"); // true
72-
///
73-
/// provider.EnsureLoaded(); // 重复调用应该快速返回
74-
/// </code>
75-
/// </example>
76-
void EnsureLoaded();
7738
}

GameFrameX.Foundation.Localization/Core/ResourceManager.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
//
55
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
66

7+
using System.Collections.Concurrent;
78
using GameFrameX.Foundation.Localization.Providers;
8-
using System.Reflection;
9-
using System.Collections.Generic;
109

1110
namespace GameFrameX.Foundation.Localization.Core;
1211

@@ -27,7 +26,7 @@ namespace GameFrameX.Foundation.Localization.Core;
2726
public class ResourceManager
2827
{
2928
private readonly List<IResourceProvider> _providers;
30-
private readonly Lazy<AssemblyResourceProvider[]> _assemblyProviders;
29+
private readonly Lazy<ConcurrentDictionary<string, AssemblyResourceProvider>> _assemblyProviders;
3130
private volatile bool _providersLoaded;
3231
private readonly object _loadLock;
3332

@@ -41,7 +40,13 @@ public class ResourceManager
4140
public ResourceManager()
4241
{
4342
_providers = new List<IResourceProvider>();
44-
_assemblyProviders = new Lazy<AssemblyResourceProvider[]>(DiscoverAssemblyProviders);
43+
_assemblyProviders = new Lazy<ConcurrentDictionary<string, AssemblyResourceProvider>>();
44+
var kvs = DiscoverAssemblyProviders();
45+
foreach (var kv in kvs)
46+
{
47+
_assemblyProviders.Value.TryAdd(kv.Key, kv.Value);
48+
}
49+
4550
_loadLock = new object();
4651
}
4752

@@ -145,7 +150,7 @@ private void LoadProviders()
145150
var assemblyProviders = _assemblyProviders.Value;
146151
foreach (var provider in assemblyProviders)
147152
{
148-
_providers.Insert(0, provider); // 插入到列表开头,优先级更高
153+
_providers.Insert(0, provider.Value); // 插入到列表开头,优先级更高
149154
}
150155
}
151156
catch (Exception ex)
@@ -163,12 +168,11 @@ private void LoadProviders()
163168
/// 查找包含本地化资源的程序集,并创建相应的资源提供者。
164169
/// 只处理已加载到内存中的程序集,不会主动加载额外的程序集。
165170
/// </remarks>
166-
private static AssemblyResourceProvider[] DiscoverAssemblyProviders()
171+
private static ConcurrentDictionary<string, AssemblyResourceProvider> DiscoverAssemblyProviders()
167172
{
173+
var providers = new ConcurrentDictionary<string, AssemblyResourceProvider>();
168174
try
169175
{
170-
var providers = new List<AssemblyResourceProvider>();
171-
172176
// 获取当前应用程序域中已加载的所有 GameFrameX 程序集
173177
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies()
174178
.Where(assembly =>
@@ -181,27 +185,27 @@ private static AssemblyResourceProvider[] DiscoverAssemblyProviders()
181185
try
182186
{
183187
// 检查程序集是否包含本地化资源
184-
var hasResources = assembly.GetManifestResourceNames()
185-
.Any(name => name.Contains(".Localization.") && name.EndsWith(".resources"));
186-
188+
var hasResources = assembly.GetManifestResourceNames().Any(name => name.Contains(".Localization.") && name.EndsWith(".resources"));
187189
if (hasResources)
188190
{
189-
providers.Add(new AssemblyResourceProvider(assembly));
191+
if (!providers.TryAdd(assembly.FullName, new AssemblyResourceProvider(assembly)))
192+
{
193+
System.Diagnostics.Debug.WriteLine($"Failed to add assembly provider for {assembly.FullName}");
194+
}
190195
}
191196
}
192197
catch (Exception ex)
193198
{
194199
System.Diagnostics.Debug.WriteLine($"Failed to check loaded assembly {assembly.FullName}: {ex.Message}");
195200
}
196201
}
197-
198-
return providers.ToArray();
199202
}
200203
catch (Exception ex)
201204
{
202205
System.Diagnostics.Debug.WriteLine($"Failed to discover assembly providers: {ex.Message}");
203-
return Array.Empty<AssemblyResourceProvider>();
204206
}
207+
208+
return providers;
205209
}
206210

207211
/// <summary>

0 commit comments

Comments
 (0)