dotnet 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;
    }
...
}

来源链接:https://www.cnblogs.com/pains/p/18686456

© 版权声明
THE END
支持一下吧
点赞12 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容