首页 > 其他分享 >dotnet CultureInfo遇到欧洲如俄文小数点是逗号想转点的解决办法

dotnet CultureInfo遇到欧洲如俄文小数点是逗号想转点的解决办法

时间:2025-01-22 17:09:45浏览次数:1  
标签:cultureInfo next 逗号 dotnet using 转点 options CultureInfo

如题,当CultureInfo是俄文(ru-RU)时,浮点数中的点是用逗号表达的,如1.1会显示成1,1,造成很多的麻烦,当然如果全系统中全部采纳逗号作为浮点也没问题,只要用户接受就可以,但有时需要继续用点号,那么解决办法如下。

1. 修改DefaultThreadCurrentCulture

我们知道CultureInfo.CurrentCulture静态变量是跟踪线程的,每个现场都有独立的CultureInfo.CurrentCulture值,它会决定当前线程的文化区域,包括时间、数字等的显示格式,这一步处理就会解决大部分浮点是逗号的问题。

var cultureInfo = new CultureInfo("ru-RU");
cultureInfo.NumberFormat.NumberDecimalSeparator = ".";
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.ReadOnly(cultureInfo);
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.ReadOnly(cultureInfo);

2. aspnetcore中间件修改CultureInfo

这一步是今天想写这个文章的原因,因为找了很长时间才发现是这里导致的问题,虽然经过上面一步的修改,我们大部分业务代码不会再用逗号了,但是当我们在aspnetcore中启用了RequestLocalizationMiddleware,就会导致例如返回json时浮点数tostring或者拼接等还是逗号的问题。
修改的办法也很简单,启动时加如下代码就可以。

services.Configure<RequestLocalizationOptions>(options=>{
  var cultures = options.SupportedCultures.Where(e => e.NumberFormat.NumberDecimalSeparator != ".").ToList();
  foreach(var c in cultures)
  {
    c.NumberFormat.NumberDecimalSeparator = ".";
  }
});

原因是因为aspnetcore中的这个中间件代码导致的,为了说明问题简化了代码(代码来自微软官方github),注意Invoke和SetCurrentThreadCulture方法是关键问题所在。

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;

namespace Microsoft.AspNetCore.Localization;

/// <summary>
/// Enables automatic setting of the culture for <see cref="HttpRequest"/>s based on information
/// sent by the client in headers and logic provided by the application.
/// </summary>
public class RequestLocalizationMiddleware
{
    private const int MaxCultureFallbackDepth = 5;

    private readonly RequestDelegate _next;
    private readonly RequestLocalizationOptions _options;
    private readonly ILogger _logger;

    /// <summary>
    /// Creates a new <see cref="RequestLocalizationMiddleware"/>.
    /// </summary>
    /// <param name="next">The <see cref="RequestDelegate"/> representing the next middleware in the pipeline.</param>
    /// <param name="options">The <see cref="RequestLocalizationOptions"/> representing the options for the
    /// <see cref="RequestLocalizationMiddleware"/>.</param>
    /// <param name="loggerFactory">The <see cref="ILoggerFactory"/> used for logging.</param>
    public RequestLocalizationMiddleware(RequestDelegate next, IOptions<RequestLocalizationOptions> options, ILoggerFactory loggerFactory)
    {
        ArgumentNullException.ThrowIfNull(options);

        _next = next ?? throw new ArgumentNullException(nameof(next));
        _logger = loggerFactory?.CreateLogger<RequestLocalizationMiddleware>() ?? throw new ArgumentNullException(nameof(loggerFactory));
        _options = options.Value;
    }

    /// <summary>
    /// Invokes the logic of the middleware.
    /// </summary>
    /// <param name="context">The <see cref="HttpContext"/>.</param>
    /// <returns>A <see cref="Task"/> that completes when the middleware has completed processing.</returns>
    public async Task Invoke(HttpContext context)
    {
        ArgumentNullException.ThrowIfNull(context);

        var requestCulture = _options.DefaultRequestCulture;
...
        if (_options.RequestCultureProviders != null)
        {
            foreach (var provider in _options.RequestCultureProviders)
            {
...
                CultureInfo? cultureInfo = null;
                CultureInfo? uiCultureInfo = null;
                if (_options.SupportedCultures != null)
                {
                    cultureInfo = GetCultureInfo(
                        cultures,
                        _options.SupportedCultures,
                        _options.FallBackToParentCultures);

                    if (cultureInfo == null)
                    {
                        _logger.UnsupportedCultures(provider.GetType().Name, cultures);
                    }
                }
...
                cultureInfo ??= _options.DefaultRequestCulture.Culture;
                uiCultureInfo ??= _options.DefaultRequestCulture.UICulture;

                var result = new RequestCulture(cultureInfo, uiCultureInfo);
                requestCulture = result;
                winningProvider = provider;
                break;
            }
        }
...
        SetCurrentThreadCulture(requestCulture);
...
        await _next(context);
    }

    private static void SetCurrentThreadCulture(RequestCulture requestCulture)
    {
        CultureInfo.CurrentCulture = requestCulture.Culture;
        CultureInfo.CurrentUICulture = requestCulture.UICulture;
    }
...
}

标签:cultureInfo,next,逗号,dotnet,using,转点,options,CultureInfo
From: https://www.cnblogs.com/pains/p/18686456

相关文章

  • dotnet最小webApi开发实践
    dotnet最小webApi开发实践软件开发过程中,经常需要写一些功能验证代码。通常是创建一个console程序来验证测试,但黑呼呼的方脑袋界面,实在是不讨人喜欢。Web开发目前已是网络世界中的主流,微软在asp.net框架大行其道之下,也整了个最小webapi项目开发向导。今天,我也拥抱一下新的开发......
  • DotNetCore 3.1桌面应用在Windows 7 SP1 X86下不能运行的问题的解决方法
    遇到的问题一个小的桌面应用,发布到Windows7SP1x86系统,打包成Self-Contained进行发布的时候,运行后没反应,也不报错。打包成SingleFile之后,运行报错api-ms-win-crt-runtime-l1-1-0.dll缺失。之后尝试安装.NetCore3.1的DesktopRuntime,问题依旧。然后又搜索一阵,大概是Windows......
  • dotnet 简单聊聊 Skia 里的 SKFontMetrics 的各项属性作用
    熟悉文本排版的伙伴也许对于字体的Metrics概念不陌生,在Skia里面提供的SKFontMetrics就包含了从字体信息里面所获取的多项信息。只是略微有所不同的是Skia多加了对字体大小的加工,即SKFontMetrics获取到的属性已经是和SKFont的Size相关如下图所示,是我绘制的示意图......
  • # dotnet ef migrations
    dotnetefmigrationsInfrastructure\DependencyInjection\InfrastructureDependencyInjection.csservices.AddDbContext<MySqlDatabase>(options=>{options.UseSqlServer(ConnectionString);});Yourtargetproject'BookApi'doesn't......
  • dotnet ef migrations
    dotnetefmigrationsInfrastructure\DependencyInjection\InfrastructureDependencyInjection.csservices.AddDbContext<MySqlDatabase>(options=>{options.UseSqlServer(ConnectionString);});Yourtargetproject'BookApi'doesn't......
  • UT 覆盖率 报告 dotnet-coverage
    安装dotnet-coverage和dotnet-reportgeneratordotnettoolinstall-gdotnet-coveragedotnettoolinstall-gdotnet-reportgenerator-globaltool运行测试,输出XML格式:dotnet-coveragecollect-fxml-ocoverage.xmldotnettest<solution/project>例如:在测试......
  • WPF 用Vlc.DotNet.Wpf实现视频播放、停止、暂停功能
    1. NuGet添加 Vlc.DotNet.Wpf 2.  到VLC官网http://www.videolan.org/下载VLC播放器。因为本机是64位的,所以下载64位,如下所示:下载的是 安装后,到安装的路径下,拷贝如下文件夹:在wpf项目的exe文件夹下,本机是 bin\Debug\net8.0-windows,新建libvlc后,再建win-x64文......
  • dotnet9 MAUI + Vue 项目
    MAUI是dotnet的跨平台技术,支持windows平台、android平台、ios平台等。使用MAUI作为基础平台,在其上运行一个前端项目,比如Vue,可以同时享受开发效率与跨平台的好处。使用dotnet9后MAUI提供的组件HybridWebView,可以实现将前端项目嵌入到MAUI项目Page中的效果。支持C#与javascript的互......
  • 达梦DOTNET驱动DM.Provider8.3.1.30495存在空字符串插入变DBNull的问题
    达梦数据库的DOTNET驱动DM.Provider,这个版本8.3.1.30495有bug,会把空字符串改成DBNull处理,反编译代码发现Dm.DmSetValue.SetString方法中判断字符串长度==0就设置成DBNull。解决办法就是降低版本到8.3.1.28188。//Dm.DmSetValueusingSystem;usingSystem.Globalization;usi......
  • dotnet core微服务框架Jimu ~部署和调用演示
     首先运行consul下载consul以开发模式运行consulagent-dev2.调试用VisualStudio2022IDE打开项目;右击解决方案-选择“属性”在属性界面下,选择多项目启动,News.Server,Auth.Server,Register.Server,ApiGateway几个项目的操作方式选择为“启动”;如......