解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
3.46 KiB
X
using System.Globalization;

namespace NewLife;

/// <summary>请求语言作用域。按 Accept-Language 设置当前 UI 文化,释放时还原</summary>
/// <remarks>
/// <see cref="Http.HttpServer"/> 默认对每个请求自动使用它;其它宿主可显式调用。
/// 仅在 <see cref="Localization.Culture"/> 为空时生效,便于宿主固定全局语言。
/// 从请求头中按 q 权重选择最高权重且存在译文表的语言;全部不支持时不改变当前 UI 文化。
/// 只修改 <see cref="CultureInfo.CurrentUICulture"/>,不修改 <see cref="CultureInfo.CurrentCulture"/>,
/// 避免影响协议中的数字与日期格式。
/// </remarks>
public sealed class RequestCultureScope : IDisposable
{
    private readonly CultureInfo? _saved;
    private readonly Boolean _changed;

    private RequestCultureScope(CultureInfo? saved, Boolean changed)
    {
        _saved = saved;
        _changed = changed;
    }

    /// <summary>按 Accept-Language 头创建请求语言作用域</summary>
    /// <param name="acceptLanguage">Accept-Language 头原始值</param>
    /// <returns>请求语言作用域;未识别到受支持语言时释放不做任何事</returns>
    public static RequestCultureScope Create(String? acceptLanguage)
    {
#if NETFRAMEWORK
        // .NET Framework 的 CurrentUICulture 为线程静态,异步请求之间可能串语言,保持宿主语言
        return new(null, false);
#else
        if (Localization.Culture != null || !TryParseAcceptLanguage(acceptLanguage, out var culture)) return new(null, false);

        var saved = CultureInfo.CurrentUICulture;
        CultureInfo.CurrentUICulture = culture!;

        return new(saved, true);
#endif
    }

    /// <summary>解析 Accept-Language 头,返回权重最高且受支持的区域性</summary>
    /// <param name="acceptLanguage">Accept-Language 头原始值</param>
    /// <returns>区域性;没有受支持语言时返回 null</returns>
    public static CultureInfo? ParseAcceptLanguage(String? acceptLanguage)
    {
        TryParseAcceptLanguage(acceptLanguage, out var culture);

        return culture;
    }

    /// <summary>还原当前 UI 文化</summary>
    public void Dispose()
    {
#if !NETFRAMEWORK
        if (_changed) CultureInfo.CurrentUICulture = _saved!;
#endif
    }

    private static Boolean TryParseAcceptLanguage(String? acceptLanguage, out CultureInfo? culture)
    {
        culture = null;
        if (acceptLanguage.IsNullOrEmpty()) return false;

        var bestQ = 0.0;
        foreach (var item in acceptLanguage.Split(','))
        {
            var parts = item.Split(';');
            var name = parts[0].Trim();
            if (name.IsNullOrEmpty() || name == "*") continue;

            var q = 1.0;
            for (var i = 1; i < parts.Length; i++)
            {
                var part = parts[i].Trim();
                if (part.StartsWith("q=", StringComparison.OrdinalIgnoreCase) &&
                    Double.TryParse(part.Substring(2), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var value))
                    q = value;
            }
            if (q <= 0 || q <= bestQ) continue;

            try
            {
                var candidate = CultureInfo.GetCultureInfo(name);
                if (!Localization.IsSupported(candidate)) continue;

                culture = candidate;
                bestQ = q;
            }
            catch (ArgumentException) { }
        }

        return culture != null;
    }
}