From 27d8f361b35e288b659a38116ca2befe54d49337 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 3 Jan 2025 19:21:33 +0800 Subject: [PATCH 01/11] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=90=88=E5=B9=B6=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Localization/Json/JsonStringLocalizer.cs | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs index 48e8f00bd0f..282e6149b69 100644 --- a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs +++ b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; +using System.Collections.Concurrent; using System.Globalization; using System.Reflection; using System.Resources; @@ -27,6 +28,8 @@ internal class JsonStringLocalizer(Assembly assembly, string typeName, string ba private ILogger Logger { get; } = logger; + private readonly ConcurrentDictionary _cache = []; + /// /// 通过指定键值获取多语言值信息索引 /// @@ -36,8 +39,13 @@ public override LocalizedString this[string name] { get { - var value = GetStringSafely(name); - return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); + if (_cache.TryGetValue(name, out var result) == false) + { + var value = GetStringSafely(name); + result = new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); + _cache.TryAdd(name, result); + } + return result; } } @@ -51,23 +59,22 @@ public override LocalizedString this[string name] { get { - var value = SafeFormat(); - return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); - - string? SafeFormat() + if (_cache.TryGetValue(name, out var result) == false) { - string? ret = null; + string? value = null; try { var format = GetStringSafely(name); - ret = string.Format(CultureInfo.CurrentCulture, format ?? name, arguments); + value = string.Format(CultureInfo.CurrentCulture, format ?? name, arguments); } catch (Exception ex) { Logger.LogError(ex, "{JsonStringLocalizerName} searched for '{Name}' in '{typeName}' with culture '{CultureName}' throw exception.", nameof(JsonStringLocalizer), name, typeName, CultureInfo.CurrentUICulture.Name); } - return ret; + result = new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); + _cache.TryAdd(name, result); } + return result; } } @@ -100,11 +107,11 @@ public override LocalizedString this[string name] private string? GetValueFromCache(IEnumerable? localizerStrings, string name) { string? ret = null; - var cultureName = CultureInfo.CurrentUICulture.Name; - var cacheKey = $"{nameof(GetValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={cultureName}"; + var cacheKey = $"{nameof(GetValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={CultureInfo.CurrentUICulture.Name}"; if (!CacheManager.GetMissingLocalizerByKey(cacheKey)) { - var l = GetLocalizedString(); + var l = localizerStrings?.FirstOrDefault(i => i.Name == name) + ?? CacheManager.GetAllStringsFromResolve().FirstOrDefault(i => i.Name == name); if (l is { ResourceNotFound: false }) { ret = l.Value; @@ -116,23 +123,12 @@ public override LocalizedString this[string name] } } return ret; - - LocalizedString? GetLocalizedString() - { - LocalizedString? localizer = null; - if (localizerStrings != null) - { - localizer = localizerStrings.FirstOrDefault(i => i.Name == name); - } - return localizer ?? CacheManager.GetAllStringsFromResolve().FirstOrDefault(i => i.Name == name); - } } private string? GetLocalizerValueFromCache(IStringLocalizer localizer, string name) { string? ret = null; - var cultureName = CultureInfo.CurrentUICulture.Name; - var cacheKey = $"{nameof(GetLocalizerValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={cultureName}"; + var cacheKey = $"{nameof(GetLocalizerValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={CultureInfo.CurrentUICulture.Name}"; if (!CacheManager.GetMissingLocalizerByKey(cacheKey)) { var l = localizer[name]; From 0daa76d455cc0d242f700aac54c14189ecafa9bd Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 3 Jan 2025 19:26:01 +0800 Subject: [PATCH 02/11] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=8F=90=E9=AB=98=E5=8F=AF=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Services/CacheManager.cs | 34 ++++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index c7e626fc05a..565fdbd3d3e 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -223,26 +223,26 @@ public static JsonLocalizationOptions GetJsonLocalizationOption() /// public static IEnumerable? GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) { - return assembly.IsDynamic ? null : GetJsonStringByTypeName(); + if (assembly.IsDynamic) + { + return null; + } - IEnumerable? GetJsonStringByTypeName() + cultureName ??= CultureInfo.CurrentUICulture.Name; + var key = $"{nameof(GetJsonStringByTypeName)}-{assembly.GetUniqueName()}-{cultureName}"; + var typeKey = $"{key}-{typeName}"; + if (forceLoad) { - cultureName ??= CultureInfo.CurrentUICulture.Name; - var key = $"{nameof(GetJsonStringByTypeName)}-{assembly.GetUniqueName()}-{cultureName}"; - var typeKey = $"{key}-{typeName}"; - if (forceLoad) - { - Instance.Cache.Remove(key); - Instance.Cache.Remove(typeKey); - } - return Instance.GetOrCreate(typeKey, entry => - { - var sections = Instance.GetOrCreate(key, entry => option.GetJsonStringFromAssembly(assembly, cultureName)); - return sections.FirstOrDefault(kv => typeName.Equals(kv.Key, StringComparison.OrdinalIgnoreCase))? - .GetChildren() - .SelectMany(kv => new[] { new LocalizedString(kv.Key, kv.Value!, false, typeName) }); - }); + Instance.Cache.Remove(key); + Instance.Cache.Remove(typeKey); } + return Instance.GetOrCreate(typeKey, entry => + { + var sections = Instance.GetOrCreate(key, entry => option.GetJsonStringFromAssembly(assembly, cultureName)); + return sections.FirstOrDefault(kv => typeName.Equals(kv.Key, StringComparison.OrdinalIgnoreCase))? + .GetChildren() + .SelectMany(kv => new[] { new LocalizedString(kv.Key, kv.Value!, false, typeName) }); + }); } /// From ef42e0b28ffa4a4859c2c8043735b25c69b7da2c Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 3 Jan 2025 19:54:36 +0800 Subject: [PATCH 03/11] =?UTF-8?q?refactor:=20=E7=B2=BE=E7=AE=80=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Services/CacheManager.cs | 23 +++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index 565fdbd3d3e..abcb053ccec 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -118,7 +118,7 @@ public void Clear(object? key) /// private void SetStartTime(DateTimeOffset startDateTimeOffset) { - GetOrCreate("BootstrapBlazor_StartTime", entry => startDateTimeOffset); + GetOrCreate("BootstrapBlazor_StartTime", _ => startDateTimeOffset); } /// @@ -159,7 +159,7 @@ public static int ElementCount(object? value) #region Localizer /// - /// + /// 通过 Type 获得 实例 /// /// /// @@ -168,10 +168,10 @@ public static int ElementCount(object? value) : Instance.Provider.GetRequiredService().Create(resourceSource); /// - /// + /// 获得 值 /// /// - public static JsonLocalizationOptions GetJsonLocalizationOption() + private static JsonLocalizationOptions GetJsonLocalizationOption() { var localizationOptions = Instance.Provider.GetRequiredService>(); return localizationOptions.Value; @@ -185,20 +185,17 @@ public static JsonLocalizationOptions GetJsonLocalizationOption() /// public static IStringLocalizer? GetStringLocalizerFromService(Assembly assembly, string typeName) => assembly.IsDynamic ? null - : Instance.GetOrCreate($"{nameof(GetStringLocalizerFromService)}-{CultureInfo.CurrentUICulture.Name}-{assembly.GetUniqueName()}-{typeName}", entry => + : Instance.GetOrCreate($"{nameof(GetStringLocalizerFromService)}-{CultureInfo.CurrentUICulture.Name}-{assembly.GetUniqueName()}-{typeName}", _ => { IStringLocalizer? ret = null; var factories = Instance.Provider.GetServices(); - if (factories != null) + var factory = factories?.LastOrDefault(a => a is not JsonStringLocalizerFactory); + if (factory != null) { - var factory = factories.LastOrDefault(a => a is not JsonStringLocalizerFactory); - if (factory != null) + var type = assembly.GetType(typeName); + if (type != null) { - var type = assembly.GetType(typeName); - if (type != null) - { - ret = factory.Create(type); - } + ret = factory.Create(type); } } return ret; From 7e06a56966cdce99c13bb06a367193c1a7eab050 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 3 Jan 2025 20:00:10 +0800 Subject: [PATCH 04/11] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=20ToList?= =?UTF-8?q?=20=E6=8F=90=E9=AB=98=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs b/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs index 95ebc85b383..7c552ca27f8 100644 --- a/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs +++ b/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs @@ -42,7 +42,7 @@ public static IEnumerable GetJsonStringFromAssembly(this assemblies.AddRange(option.AdditionalJsonAssemblies); } - var streams = assemblies.SelectMany(i => option.GetResourceStream(i, cultureName)); + var streams = assemblies.SelectMany(i => option.GetResourceStream(i, cultureName)).ToList(); // 添加 Json 文件流到配置 foreach (var s in streams) From b34781ae420932319ec237e7abd67d2373e22759 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 3 Jan 2025 20:04:29 +0800 Subject: [PATCH 05/11] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LocalizationOptionsExtensions.cs | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs b/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs index 7c552ca27f8..55f51c52a6b 100644 --- a/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs +++ b/src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs @@ -27,16 +27,14 @@ public static IEnumerable GetJsonStringFromAssembly(this var builder = new ConfigurationBuilder(); // 获取程序集中的资源文件 - var assemblies = new List() - { - assembly - }; + var assemblies = new List() { assembly }; var entryAssembly = GetAssembly(); if (assembly != entryAssembly) { assemblies.Add(entryAssembly); } + if (option.AdditionalJsonAssemblies != null) { assemblies.AddRange(option.AdditionalJsonAssemblies); @@ -120,16 +118,17 @@ void AddStream(string name) // 开启回落机制并且当前文化信息与回落语言相同 bool EqualFallbackCulture(string name) => option.EnableFallbackCulture && option.FallbackCulture == name; + } - StringSegment GetParentCultureName(StringSegment cultureInfoName) + static StringSegment GetParentCultureName(StringSegment cultureInfoName) + { + var ret = new StringSegment(); + var index = cultureInfoName.IndexOf('-'); + if (index > 0) { - var ret = new StringSegment(); - var index = cultureInfoName.IndexOf('-'); - if (index > 0) - { - ret = cultureInfoName.Subsegment(0, index); - } - return ret; + ret = cultureInfoName.Subsegment(0, index); } + + return ret; } } From 98bdb30d8c3674a56050c07620758c43a29f017b Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 3 Jan 2025 20:08:45 +0800 Subject: [PATCH 06/11] =?UTF-8?q?Revert=20"refactor:=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=90=88=E5=B9=B6=E5=87=BD=E6=95=B0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 27d8f361b35e288b659a38116ca2befe54d49337. --- .../Localization/Json/JsonStringLocalizer.cs | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs index 282e6149b69..48e8f00bd0f 100644 --- a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs +++ b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; -using System.Collections.Concurrent; using System.Globalization; using System.Reflection; using System.Resources; @@ -28,8 +27,6 @@ internal class JsonStringLocalizer(Assembly assembly, string typeName, string ba private ILogger Logger { get; } = logger; - private readonly ConcurrentDictionary _cache = []; - /// /// 通过指定键值获取多语言值信息索引 /// @@ -39,13 +36,8 @@ public override LocalizedString this[string name] { get { - if (_cache.TryGetValue(name, out var result) == false) - { - var value = GetStringSafely(name); - result = new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); - _cache.TryAdd(name, result); - } - return result; + var value = GetStringSafely(name); + return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); } } @@ -59,22 +51,23 @@ public override LocalizedString this[string name] { get { - if (_cache.TryGetValue(name, out var result) == false) + var value = SafeFormat(); + return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); + + string? SafeFormat() { - string? value = null; + string? ret = null; try { var format = GetStringSafely(name); - value = string.Format(CultureInfo.CurrentCulture, format ?? name, arguments); + ret = string.Format(CultureInfo.CurrentCulture, format ?? name, arguments); } catch (Exception ex) { Logger.LogError(ex, "{JsonStringLocalizerName} searched for '{Name}' in '{typeName}' with culture '{CultureName}' throw exception.", nameof(JsonStringLocalizer), name, typeName, CultureInfo.CurrentUICulture.Name); } - result = new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: typeName); - _cache.TryAdd(name, result); + return ret; } - return result; } } @@ -107,11 +100,11 @@ public override LocalizedString this[string name] private string? GetValueFromCache(IEnumerable? localizerStrings, string name) { string? ret = null; - var cacheKey = $"{nameof(GetValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={CultureInfo.CurrentUICulture.Name}"; + var cultureName = CultureInfo.CurrentUICulture.Name; + var cacheKey = $"{nameof(GetValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={cultureName}"; if (!CacheManager.GetMissingLocalizerByKey(cacheKey)) { - var l = localizerStrings?.FirstOrDefault(i => i.Name == name) - ?? CacheManager.GetAllStringsFromResolve().FirstOrDefault(i => i.Name == name); + var l = GetLocalizedString(); if (l is { ResourceNotFound: false }) { ret = l.Value; @@ -123,12 +116,23 @@ public override LocalizedString this[string name] } } return ret; + + LocalizedString? GetLocalizedString() + { + LocalizedString? localizer = null; + if (localizerStrings != null) + { + localizer = localizerStrings.FirstOrDefault(i => i.Name == name); + } + return localizer ?? CacheManager.GetAllStringsFromResolve().FirstOrDefault(i => i.Name == name); + } } private string? GetLocalizerValueFromCache(IStringLocalizer localizer, string name) { string? ret = null; - var cacheKey = $"{nameof(GetLocalizerValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={CultureInfo.CurrentUICulture.Name}"; + var cultureName = CultureInfo.CurrentUICulture.Name; + var cacheKey = $"{nameof(GetLocalizerValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={cultureName}"; if (!CacheManager.GetMissingLocalizerByKey(cacheKey)) { var l = localizer[name]; From 05b0c6037b20d31cf198096e7cae9a2b7f97772f Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 3 Jan 2025 20:53:38 +0800 Subject: [PATCH 07/11] perf: use Frozen data type improve performance --- .../Extensions/CacheManagerExtensions.cs | 3 +- .../Localization/Json/JsonStringLocalizer.cs | 23 +++++++------- src/BootstrapBlazor/Services/CacheManager.cs | 31 ++++++++++++++++--- src/BootstrapBlazor/Utils/Utility.cs | 18 +++++++---- 4 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs b/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs index 5d07de3f5a6..29c8840579c 100644 --- a/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs +++ b/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs @@ -4,6 +4,7 @@ // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone using Microsoft.Extensions.Caching.Memory; +using System.Collections.Frozen; using System.Globalization; namespace BootstrapBlazor.Server.Extensions; @@ -20,7 +21,7 @@ internal static class CacheManagerExtensions /// /// /// - public static IEnumerable GetLocalizedStrings(this ICacheManager cache, string typeName, JsonLocalizationOptions options) + public static FrozenSet GetLocalizedStrings(this ICacheManager cache, string typeName, JsonLocalizationOptions options) { var key = $"Snippet-{CultureInfo.CurrentUICulture.Name}-{nameof(GetLocalizedStrings)}-{typeName}"; return cache.GetOrCreate(key, entry => diff --git a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs index 48e8f00bd0f..c1ddc835790 100644 --- a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs +++ b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs @@ -9,6 +9,10 @@ using System.Reflection; using System.Resources; +#if NET8_0_OR_GREATER +using System.Collections.Frozen; +#endif + namespace BootstrapBlazor.Components; /// @@ -97,14 +101,19 @@ public override LocalizedString this[string name] } } - private string? GetValueFromCache(IEnumerable? localizerStrings, string name) +#if NET8_0_OR_GREATER + private string? GetValueFromCache(FrozenSet? localizerStrings, string name) +#else + private string? GetValueFromCache(HashSet? localizerStrings, string name) +#endif { string? ret = null; var cultureName = CultureInfo.CurrentUICulture.Name; var cacheKey = $"{nameof(GetValueFromCache)}&name={name}&{Assembly.GetUniqueName()}&type={typeName}&culture={cultureName}"; if (!CacheManager.GetMissingLocalizerByKey(cacheKey)) { - var l = GetLocalizedString(); + var l = localizerStrings?.FirstOrDefault(i => i.Name == name) + ?? CacheManager.GetAllStringsFromResolve().FirstOrDefault(i => i.Name == name); if (l is { ResourceNotFound: false }) { ret = l.Value; @@ -116,16 +125,6 @@ public override LocalizedString this[string name] } } return ret; - - LocalizedString? GetLocalizedString() - { - LocalizedString? localizer = null; - if (localizerStrings != null) - { - localizer = localizerStrings.FirstOrDefault(i => i.Name == name); - } - return localizer ?? CacheManager.GetAllStringsFromResolve().FirstOrDefault(i => i.Name == name); - } } private string? GetLocalizerValueFromCache(IStringLocalizer localizer, string name) diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index abcb053ccec..bb1cd83f9bd 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -12,6 +12,10 @@ using System.Linq.Expressions; using System.Reflection; +#if NET8_0_OR_GREATER +using System.Collections.Frozen; +#endif + namespace BootstrapBlazor.Components; /// @@ -206,8 +210,12 @@ private static JsonLocalizationOptions GetJsonLocalizationOption() /// /// /// - /// - public static IEnumerable? GetAllStringsByTypeName(Assembly assembly, string typeName) => GetJsonStringByTypeName(GetJsonLocalizationOption(), assembly, typeName, CultureInfo.CurrentUICulture.Name); +#if NET8_0_OR_GREATER + public static FrozenSet? GetAllStringsByTypeName(Assembly assembly, string typeName) +#else + public static HashSet? GetAllStringsByTypeName(Assembly assembly, string typeName) +#endif + => GetJsonStringByTypeName(GetJsonLocalizationOption(), assembly, typeName, CultureInfo.CurrentUICulture.Name); /// /// 通过指定程序集获取所有本地化信息键值集合 @@ -218,7 +226,11 @@ private static JsonLocalizationOptions GetJsonLocalizationOption() /// cultureName 未空时使用 CultureInfo.CurrentUICulture.Name /// 默认 false 使用缓存值 设置 true 时内部强制重新加载 /// - public static IEnumerable? GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) +#if NET8_0_OR_GREATER + public static FrozenSet? GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) +#else + public static HashSet? GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) +#endif { if (assembly.IsDynamic) { @@ -236,9 +248,14 @@ private static JsonLocalizationOptions GetJsonLocalizationOption() return Instance.GetOrCreate(typeKey, entry => { var sections = Instance.GetOrCreate(key, entry => option.GetJsonStringFromAssembly(assembly, cultureName)); - return sections.FirstOrDefault(kv => typeName.Equals(kv.Key, StringComparison.OrdinalIgnoreCase))? + var items = sections.FirstOrDefault(kv => typeName.Equals(kv.Key, StringComparison.OrdinalIgnoreCase))? .GetChildren() .SelectMany(kv => new[] { new LocalizedString(kv.Key, kv.Value!, false, typeName) }); +#if NET8_0_OR_GREATER + return items?.ToFrozenSet(); +#else + return items?.ToHashSet(); +#endif }); } @@ -247,7 +264,11 @@ private static JsonLocalizationOptions GetJsonLocalizationOption() /// /// /// - public static IEnumerable GetAllStringsFromResolve(bool includeParentCultures = true) => Instance.GetOrCreate($"{nameof(GetAllStringsFromResolve)}-{CultureInfo.CurrentUICulture.Name}", entry => Instance.Provider.GetRequiredService().GetAllStringsByCulture(includeParentCultures)); +#if NET8_0_OR_GREATER + public static FrozenSet GetAllStringsFromResolve(bool includeParentCultures = true) => Instance.GetOrCreate($"{nameof(GetAllStringsFromResolve)}-{CultureInfo.CurrentUICulture.Name}", entry => Instance.Provider.GetRequiredService().GetAllStringsByCulture(includeParentCultures).ToFrozenSet()); +#else + public static HashSet GetAllStringsFromResolve(bool includeParentCultures = true) => Instance.GetOrCreate($"{nameof(GetAllStringsFromResolve)}-{CultureInfo.CurrentUICulture.Name}", entry => Instance.Provider.GetRequiredService().GetAllStringsByCulture(includeParentCultures).ToHashSet()); +#endif /// /// 查询缺失本地化资源项目 diff --git a/src/BootstrapBlazor/Utils/Utility.cs b/src/BootstrapBlazor/Utils/Utility.cs index e8ff2771818..fba12e288ec 100644 --- a/src/BootstrapBlazor/Utils/Utility.cs +++ b/src/BootstrapBlazor/Utils/Utility.cs @@ -10,6 +10,10 @@ using System.Linq.Expressions; using System.Reflection; +#if NET8_0_OR_GREATER +using System.Collections.Frozen; +#endif + namespace BootstrapBlazor.Components; /// @@ -156,8 +160,11 @@ public static class Utility /// 类名称 /// cultureName 未空时使用 CultureInfo.CurrentUICulture.Name /// 默认 false 使用缓存值 设置 true 时内部强制重新加载 - /// - public static IEnumerable GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) => CacheManager.GetJsonStringByTypeName(option, assembly, typeName, cultureName, forceLoad) ?? []; +#if NET8_0_OR_GREATER + public static FrozenSet GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) => CacheManager.GetJsonStringByTypeName(option, assembly, typeName, cultureName, forceLoad) ?? FrozenSet.Empty; +#else + public static HashSet GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) => CacheManager.GetJsonStringByTypeName(option, assembly, typeName, cultureName, forceLoad) ?? new HashSet(); +#endif /// /// 通过指定程序集与类型获得 IStringLocalizer 实例 @@ -367,7 +374,7 @@ public static IEnumerable GetTableColumns(Type type, IEnumerable OrderFunc(this IEnumerable cols) => cols + internal static IEnumerable OrderFunc(this List cols) => cols .Where(a => a.Order > 0).OrderBy(a => a.Order) .Concat(cols.Where(a => a.Order == 0)) .Concat(cols.Where(a => a.Order < 0).OrderBy(a => a.Order)); @@ -404,7 +411,6 @@ public static void CreateDisplayByFieldType(this RenderTreeBuilder builder, IEdi builder.AddAttribute(50, "class", col.CssClass); } builder.AddMultipleAttributes(60, item.ComponentParameters); - builder.CloseComponent(); } else if (item.ComponentType == typeof(Textarea) || item.Rows > 0) { @@ -422,7 +428,6 @@ public static void CreateDisplayByFieldType(this RenderTreeBuilder builder, IEdi builder.AddAttribute(60, "class", col.CssClass); } builder.AddMultipleAttributes(70, item.ComponentParameters); - builder.CloseComponent(); } else { @@ -448,8 +453,9 @@ public static void CreateDisplayByFieldType(this RenderTreeBuilder builder, IEdi builder.AddAttribute(90, "class", col.CssClass); } builder.AddMultipleAttributes(100, item.ComponentParameters); - builder.CloseComponent(); } + + builder.CloseComponent(); } /// From dd78b6e73d6214e7c2f50755c593b592843dd535 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 4 Jan 2025 10:24:52 +0800 Subject: [PATCH 08/11] =?UTF-8?q?refactor:=20=E6=92=A4=E9=94=80=E6=9B=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/CacheManagerExtensions.cs | 2 +- .../Localization/Json/JsonStringLocalizer.cs | 10 +--------- src/BootstrapBlazor/Services/CacheManager.cs | 12 ++---------- src/BootstrapBlazor/Utils/Utility.cs | 10 +--------- 4 files changed, 5 insertions(+), 29 deletions(-) diff --git a/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs b/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs index 29c8840579c..cf42d38a75d 100644 --- a/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs +++ b/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs @@ -21,7 +21,7 @@ internal static class CacheManagerExtensions /// /// /// - public static FrozenSet GetLocalizedStrings(this ICacheManager cache, string typeName, JsonLocalizationOptions options) + public static IEnumerable GetLocalizedStrings(this ICacheManager cache, string typeName, JsonLocalizationOptions options) { var key = $"Snippet-{CultureInfo.CurrentUICulture.Name}-{nameof(GetLocalizedStrings)}-{typeName}"; return cache.GetOrCreate(key, entry => diff --git a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs index c1ddc835790..de80a67cf6d 100644 --- a/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs +++ b/src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs @@ -9,10 +9,6 @@ using System.Reflection; using System.Resources; -#if NET8_0_OR_GREATER -using System.Collections.Frozen; -#endif - namespace BootstrapBlazor.Components; /// @@ -101,11 +97,7 @@ public override LocalizedString this[string name] } } -#if NET8_0_OR_GREATER - private string? GetValueFromCache(FrozenSet? localizerStrings, string name) -#else - private string? GetValueFromCache(HashSet? localizerStrings, string name) -#endif + private string? GetValueFromCache(IEnumerable? localizerStrings, string name) { string? ret = null; var cultureName = CultureInfo.CurrentUICulture.Name; diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index bb1cd83f9bd..d65d0d6051b 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -210,11 +210,7 @@ private static JsonLocalizationOptions GetJsonLocalizationOption() /// /// /// -#if NET8_0_OR_GREATER - public static FrozenSet? GetAllStringsByTypeName(Assembly assembly, string typeName) -#else - public static HashSet? GetAllStringsByTypeName(Assembly assembly, string typeName) -#endif + public static IEnumerable? GetAllStringsByTypeName(Assembly assembly, string typeName) => GetJsonStringByTypeName(GetJsonLocalizationOption(), assembly, typeName, CultureInfo.CurrentUICulture.Name); /// @@ -226,11 +222,7 @@ private static JsonLocalizationOptions GetJsonLocalizationOption() /// cultureName 未空时使用 CultureInfo.CurrentUICulture.Name /// 默认 false 使用缓存值 设置 true 时内部强制重新加载 /// -#if NET8_0_OR_GREATER - public static FrozenSet? GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) -#else - public static HashSet? GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) -#endif + public static IEnumerable? GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) { if (assembly.IsDynamic) { diff --git a/src/BootstrapBlazor/Utils/Utility.cs b/src/BootstrapBlazor/Utils/Utility.cs index fba12e288ec..e09738f8583 100644 --- a/src/BootstrapBlazor/Utils/Utility.cs +++ b/src/BootstrapBlazor/Utils/Utility.cs @@ -10,10 +10,6 @@ using System.Linq.Expressions; using System.Reflection; -#if NET8_0_OR_GREATER -using System.Collections.Frozen; -#endif - namespace BootstrapBlazor.Components; /// @@ -160,11 +156,7 @@ public static class Utility /// 类名称 /// cultureName 未空时使用 CultureInfo.CurrentUICulture.Name /// 默认 false 使用缓存值 设置 true 时内部强制重新加载 -#if NET8_0_OR_GREATER - public static FrozenSet GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) => CacheManager.GetJsonStringByTypeName(option, assembly, typeName, cultureName, forceLoad) ?? FrozenSet.Empty; -#else - public static HashSet GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) => CacheManager.GetJsonStringByTypeName(option, assembly, typeName, cultureName, forceLoad) ?? new HashSet(); -#endif + public static IEnumerable GetJsonStringByTypeName(JsonLocalizationOptions option, Assembly assembly, string typeName, string? cultureName = null, bool forceLoad = false) => CacheManager.GetJsonStringByTypeName(option, assembly, typeName, cultureName, forceLoad) ?? []; /// /// 通过指定程序集与类型获得 IStringLocalizer 实例 From 22195562c1b6318be1ad00085fa081b8db8ad522 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 4 Jan 2025 10:25:36 +0800 Subject: [PATCH 09/11] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Performance/CacheTest.cs | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/UnitTest/Performance/CacheTest.cs b/test/UnitTest/Performance/CacheTest.cs index 8915958852c..57bd2383dfd 100644 --- a/test/UnitTest/Performance/CacheTest.cs +++ b/test/UnitTest/Performance/CacheTest.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Localization; using System.Collections.Concurrent; +using System.Collections.Frozen; using System.Diagnostics; namespace UnitTest.Performance; @@ -53,6 +54,35 @@ public void Cache_Ok() IEnumerable CacheMethod() => cache.GetOrAdd("test", key => NoCacheMethod()); } + [Fact] + public void List_Perf() + { + var listItms = GetListLocalizedStrings(); + var setItems = GetSetLocalizedStrings(); + var frozenItems = GetFrozenLocalizedStrings(); + + var sw = Stopwatch.StartNew(); + listItms.FirstOrDefault(i => i.Name == "500000"); + sw.Stop(); + var sp1 = sw.Elapsed; + + sw.Restart(); + setItems.FirstOrDefault(i => i.Name == "500000"); + sw.Stop(); + var sp2 = sw.Elapsed; + + sw.Restart(); + frozenItems.FirstOrDefault(i => i.Name == "500000"); + sw.Stop(); + var sp3 = sw.Elapsed; + } + + private IEnumerable GetListLocalizedStrings() => Enumerable.Range(1, 1000000).Select(i => new LocalizedString($"{i}", $"{i}", false, nameof(CacheTest))); + + private IEnumerable GetSetLocalizedStrings() => Enumerable.Range(1, 1000000).Select(i => new LocalizedString($"{i}", $"{i}", false, nameof(CacheTest))).ToHashSet(); + + private IEnumerable GetFrozenLocalizedStrings() => Enumerable.Range(1, 1000000).Select(i => new LocalizedString($"{i}", $"{i}", false, nameof(CacheTest))).ToFrozenSet(); + private IEnumerable NoCacheMethod() => Enumerable.Range(1, 80).Select(i => new Foo() { Id = i, From 76a84c69240d4b39e84e5d467052aca77ef6a064 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 4 Jan 2025 10:26:19 +0800 Subject: [PATCH 10/11] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E4=B8=8D?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs b/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs index cf42d38a75d..5d07de3f5a6 100644 --- a/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs +++ b/src/BootstrapBlazor.Server/Extensions/CacheManagerExtensions.cs @@ -4,7 +4,6 @@ // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone using Microsoft.Extensions.Caching.Memory; -using System.Collections.Frozen; using System.Globalization; namespace BootstrapBlazor.Server.Extensions; From e36a111f9349452f8099c25c8a9d6060f2df4ca1 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 4 Jan 2025 10:32:03 +0800 Subject: [PATCH 11/11] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E5=8F=AF?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Services/CacheManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index d65d0d6051b..936a8b3302f 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -193,7 +193,7 @@ private static JsonLocalizationOptions GetJsonLocalizationOption() { IStringLocalizer? ret = null; var factories = Instance.Provider.GetServices(); - var factory = factories?.LastOrDefault(a => a is not JsonStringLocalizerFactory); + var factory = factories.LastOrDefault(a => a is not JsonStringLocalizerFactory); if (factory != null) { var type = assembly.GetType(typeName);