• [Asp.net 5] Localization-Asp.net运行时多语言


    本节介绍的是Microsoft.AspNet.Localization工程。该工程是运行在Asp.net 5环境中的运行时多语言设置。

    ASP.net 5中间件技术

    在新的Asp.net 5中,可以将组件组册到asp.net环境中。注册是通过接口IApplicationBuilder的扩展方法实现的。

     public static IApplicationBuilder UseMiddleware(this IApplicationBuilder builder, Type middleware, params object[] args)

    [该扩展方法通过可变参数args传递所需要的参数以及外的RequestDelegate(delegate Task RequestDelegate(HttpContext context))类型(系统会在内部给该类型参数赋值)。创建Type(middleware)类型实例。之后调用Type(middleware)的Invoke方法,不过和构造函数不同的是,当Invoke方法参数大于一个时,参数全部来自于以来注入,而不是args]

    通过IApplicationBuilder注入的中间件,必须有一个方法是Invoke,Invoke方法的参数是可变参数,长度不受限制,系统会从asp.net的反转控制中获取参数;系统之后会调用该Invoke方法。[此处有疑问:为啥不定义成包含invoke方法的接口,更加面向对象]

    我们在Microsoft.AspNet.Localization工程中可以找到俩个类:

    • IApplicationBuilderExtensions 中间注册方法,在Microsoft.AspNet.Localization工程中的实现。
    • RequestLocalizationMiddleware 中间件类,是Microsoft.AspNet.Localization的入口。
        public static class IApplicationBuilderExtensions
        {
            public static IApplicationBuilder UseRequestLocalization([NotNull] this IApplicationBuilder builder)
            {
                var options = new RequestLocalizationOptions();
    
                return UseRequestLocalization(builder, options);
            }
    
            public static IApplicationBuilder UseRequestLocalization(
                [NotNull] this IApplicationBuilder builder,
                [NotNull] RequestLocalizationOptions options)
                => builder.UseMiddleware<RequestLocalizationMiddleware>(options);
        }
    IApplicationBuilderExtensions
        public class RequestLocalizationMiddleware
        {
            private readonly RequestDelegate _next;
            private readonly RequestLocalizationOptions _options;
            
            public RequestLocalizationMiddleware([NotNull] RequestDelegate next, [NotNull] RequestLocalizationOptions options)
            {
                _next = next;
                _options = options;
            }
    
            public async Task Invoke([NotNull] HttpContext context)
            {
                var requestCulture = _options.DefaultRequestCulture ??
                    new RequestCulture(CultureInfo.CurrentCulture, CultureInfo.CurrentUICulture);
    
                IRequestCultureProvider winningProvider = null;
    
                if (_options.RequestCultureProviders != null)
                {
                    foreach (var provider in _options.RequestCultureProviders)
                    {
                        var result = await provider.DetermineRequestCulture(context);
                        if (result != null)
                        {
                            requestCulture = result;
                            winningProvider = provider;
                            break;
                        }
                    }
                }
    
                context.SetFeature<IRequestCultureFeature>(new RequestCultureFeature(requestCulture, winningProvider));
    
                SetCurrentThreadCulture(requestCulture);
    
                await _next(context);
            }
    
            private static void SetCurrentThreadCulture(RequestCulture requestCulture)
            {
    #if DNX451
                Thread.CurrentThread.CurrentCulture = requestCulture.Culture;
                Thread.CurrentThread.CurrentUICulture = requestCulture.UICulture;
    #else
                CultureInfo.CurrentCulture = requestCulture.Culture;
                CultureInfo.CurrentUICulture = requestCulture.UICulture;
    #endif
            }
        }
    RequestLocalizationMiddleware

    注册前的参数RequestLocalizationOptions 

    IApplicationBuilderExtensions中,我们对于中间件RequestLocalizationMiddleware注册时,需要传入RequestLocalizationOptions类型的实例,大多数时候传入的都是默认的无参实例。

    我们看RequestLocalizationOptions类只有4个属性,代码如下:

    public class RequestLocalizationOptions
        {
            public RequestLocalizationOptions()
            {
                DefaultRequestCulture = new RequestCulture(CultureInfo.CurrentCulture, CultureInfo.CurrentUICulture);
    
                RequestCultureProviders = new List<IRequestCultureProvider>
                {
                    new QueryStringRequestCultureProvider { Options = this },
                    new CookieRequestCultureProvider { Options = this },
                    new AcceptLanguageHeaderRequestCultureProvider { Options = this }
                };
            }
            public RequestCulture DefaultRequestCulture { get; set; }
            public IList<CultureInfo> SupportedCultures { get; set; }
            public IList<CultureInfo> SupportedUICultures { get; set; }
            public IList<IRequestCultureProvider> RequestCultureProviders { get; set; }
        }
    View Code

    我们看到在无参的构造函数中,系统初始化了DefaultRequestCulture和RequestCultureProviders。系统会遍历RequestCultureProviders寻找适应的语言,当找不到合适的语言时,使用DefaultRequestCulture。

    • RequestCultureProviders:默认初始化三种多语言提供源:queryString、cookie、acceptHeader。
    • SupportedCultures:系统支持的语言
    • SupportedUICultures:系统支持的UI语言
    • DefaultRequestCulture:默认的语言源

    [当我们需要自定义RequestCultureProvider时,我们有俩种方式,自定义类继承类RequestCultureProvider(或者直接继承接口IRequestCultureProvider),或者将CustomRequestCultureProvider注册到RequestCultureProviders中,并在CustomRequestCultureProvider类构造函数中注册Task<RequestCulture>方法]

    注册时的顺序

    系统是按照RequestLocalizationOptions中RequestCultureProviders的顺序获取合适的语言,如果没有则使用DefaultRequestCulture。默认情况,系统会根据queryString、cookie、acceptHeader(默认最多取前三项语言)的顺序读取<是短路算法>。

    注册后的RequestCultureFeature

    Asp.net5 的运行时环境Context可以注册不同类型的参数,所以系统最后注册了IRequestCultureFeature接口的实例。

     context.SetFeature<IRequestCultureFeature>(new RequestCultureFeature(requestCulture, winningProvider));

    整体结构

    整个工程的文件可以用以下结构表示:

  • 相关阅读:
    阅读编程书籍的方法(转)
    Java 面向对象概念
    Python 统计文本中单词的个数
    Python 学习笔记(五)杂项
    在CentOS7环境下部署TiDB
    前端学习之路:第三章、来做个天气应用吧(1)
    前端学习之路:第二章、Vue-router和axios
    前端学习之路:第一章、开始使用Vue
    在Docker下搭建Apache+PHP+mysql环境的过程记录
    在基于Windows系统的PHP后端中引入Redis
  • 原文地址:https://www.cnblogs.com/watermoon2/p/4544094.html
Copyright © 2020-2023  润新知