• ASP.NET Core学习


    1. .net core是.net生态发展的未来;是微软重新设计的、和FW比整个体系、结构完全变化了。
    2. 开源、跨平台(开发、部署、物联网、云服务)
    3. 模块化、组件化、体积小、运行速度快
    4. 维护:不是微软一家了,而有一个社区、.net基金
    5. 微服务、docker
    6. 3.0前包含移植了.net fw类库,3.0后不一样了。
    7. 运行命令行(vs code)、部署灵活
    8. 向下兼容(与FW兼容)
    9. .Net Core目前3.1,下一代.Net5(16年.net core1,19年.net core 3.1)
    10. .net core3.1目前支持:winformwpf不太完善、asp.net core 3.0、EF core 3.0
    • ASP.NET CORE 学习要点:

      启动流程、主机配置、IOC、服务、管道、中间件、应用配置、多环境、日志、路由、异常、处理、静态文件、部署

    • 启动:自宿主、IIS 2种

    入口点:Startup.cs

    看代码:Program.cs

        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                //这里默认配置
                //环境变量(DotNet开关)
                //加载命令行参数
                //加载应用配置
                //配置的默认日志组件
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        //这里进行-组件配置
                        //webBuilder.ConfigureKestrel((context,option)=>option.Limits.MaxRequestBodySize=1024);//示例
                        //webBuilder.ConfigureLogging((context,builder)=>builder...;
    
                        //这里是-主机配置项
                        webBuilder.UseStartup<Startup>();
    
                        //配置主机的方式:
                        //(1)硬编码
                        //(2)环境变量(ASPNETCORE开关的,不管配置在什么地方)
                        //(3) 应用配置(appsettings.json)
                        //(4)命令行(优先级最高)
    
                        //这里改变了端口(这里的硬编码先生效了,端口实际默认配置在Properties下面的launchSettings.json中)
                        webBuilder.UseUrls("http://*:6000");
                        //也可以在命令行(bin目录下)运行命令启动:dotnet WebApplication-NetCoreTest.dll --urls http://*:7999
    
                    });
    
        }

     通过下面的命令行运行看,代码中虽然配置了6000端口,但命令行优先级最高 

    • Host.CreateDefaultBuilder主机:管理web应用程序启动、生存期管理、配置、请求处理管道、日志、IOC(实际是封装了应用资源的一个对象)
    • 流程:创建主机生成器》配置》创建主机》运行主机
    • kestrel:跨平台、类IIS、高性能、支持HTTPSHTTPS/2、在linux下性能更高、不支持反向代理、负载均衡(主要用于后端WEB托管、调试,最好不放在前端,应该用iis ginx代替)

     http请求 > 反向代理 > webserver kertrl > 中间件 > 返回给客户

     

     

    • 配置介绍

      • 命令行配置(通过运行时在命令行里输入的参数)=========默认参数(代码里的硬编码参数)
      • Json文件配置(使用json文件的配置)
      • 从配置文件文本到c#对象实例的映射 - Options 与 Bind(将配置文件的配置绑定到一个C#的类【直接映射】https://blog.csdn.net/Upgrader/article/details/104785213/
      • 配置文件热更新(不用重新启动)【用IoptionSnapeShot】
      • 框架设计:Configuration
    • 其他配置:

      • (已安装或已创建的)自定义提供程序
      • 目录文件
      • 环境变量
      • 内存中的 .NET 对象

       net core 中的配置====参考资源https://www.w3cschool.cn/netcore/netcore-vaqb31ks.html

     依赖注入:

    参考资源:http://www.jessetalk.cn/2017/11/06/di-in-aspnetcore/

    实现方式:通过依赖倒置和IOC容器注入来实现的

    • 客户端new一个对象时,不依赖于具体实现,而依赖于一个抽象
    • 通过IOC容器将对象注入进来,而不是客户端类自己去new一个对象【不用自己去拿,而是别人拿什么来,你就用什么】

    优点:

    • 解耦:对于客户端类来说,解除对 对象的强依赖,很容易替换掉依赖的类,对于被引用过很多次的类很容易就替换掉了【容器给你什么对像就用什么对象】
    • 松耦合让代码更具灵活性,能更好地应对需求变动综上所述项目维护将带来好处。
    • 单元测试友好:在测试方法里,直接new各种对象,然后扔到一个controler的构造函数里就可以了。

    注入的方式:

    • 构造函数注入
    • 属性注入

    隐式依赖:把一个类用到的所有外部组件放到一个类最上面,在构造函数里面初始化

    private CustomerContext _context;
    
    public CustomerController()
    {
        _context = new CustomerContext(new DbContextOptions<CustomerContext>{});
    }

    显示依赖:需要用到的地方再初始化,不推荐

    var context = new CustomerContext(new DbContextOptions<CustomerContext>{});

    实例的生命周期之单例

    .NET Core DI 为我们提供的实例生命周其包括三种
    • Transient: 每一次GetService都会创建一个新的实例
    • Scoped:  在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内)
    • Singleton :整个应用程序生命周期以内只创建一个实例 

    DI在ASP.NET Core中的应用

    • 在Startup类中初始化:Startup.cs的  ConfigureService中配置DI,大家看到 IServiceCollection这个参数应该就比较熟悉了
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<ILoginService<ApplicationUser>, 
          EFLoginService>();
        services.AddMvc();
    )
    • Controller中使用:一般可以通过构造函数或者属性来实现注入,但是官方推荐是通过构造函数。这也是所谓的显式依

     private ILoginService<ApplicationUser> _loginService;
    public AccountController(
      ILoginService<ApplicationUser> loginService)
    {
      _loginService = loginService;
    }
    • View中使用:在View中需要用@inject 再声明一下,起一个别名。

    @using MilkStone.Services;
    @model MilkStone.Models.AccountViewModel.LoginViewModel
    @inject ILoginService<ApplicationUser>  loginService
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head></head>
    <body>
      @loginService.GetUserName()
    </body>
    </html>
    • 通过 HttpContext来获取实例

    HttpContext下有一个RequestedService同样可以用来获取实例对象,不过这种方法一般不推荐。同时要注意GetService<>这是个范型方法,默认如果没有添加Microsoft.Extension.DependencyInjection的using,是不用调用这个方法的。

    HttpContext.RequestServices.GetService<ILoginService<ApplicationUser>>();

    如何替换其它的Ioc容器

    Autofac也是不错的选择,但我们首先要搞清楚为什么要替换掉默认的 DI容器?,替换之后有什么影响?.NET Core默认的实现对于一些小型的项目完全够用,甚至大型项目麻烦点也能用,但是会有些麻烦,原因在于只提供了最基本的AddXXXX方法来绑定实例关系,需要一个一个的添加。如果项目可能要添加好几百行这样的方法。
     
    如果熟悉Autofac的同学可能会这下面这样的代码有映象。
    builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>));
     
    builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>));

    这会给我们的初始化带来一些便利性,我们来看看如何替换Autofac到ASP.NET Core。我们只需要把Startup类里面的 ConfigureService的 返回值从 void改为 IServiceProvider即可。而返回的则是一个AutoServiceProvider。

    public IServiceProvider ConfigureServices(
      IServiceCollection services){
        services.AddMvc();
        // Add other framework services
    
        // Add Autofac
        var containerBuilder = new ContainerBuilder();
        containerBuilder.RegisterModule<DefaultModule>();
        containerBuilder.Populate(services);
        var container = containerBuilder.Build();
        return new AutofacServiceProvider(container);
    }

    其中很大的一个变化在于:Autofac 原来的一个生命周期InstancePerRequest,将不再有效。正如我们前面所说的,整个request的生命周期被ASP.NET Core管理了,所以Autofac的这个将不再有效。我们可以使用 InstancePerLifetimeScope ,同样是有用的,对应了我们ASP.NET Core DI 里面的Scoped。 

    • 管道:

      • 用于检查、重路由或修改传入请求和传出响应
      • 基于中间件组件而形成的管道(Startup.Configure方法中通过IApplicationBuilder的在使用Use方法添加中间件)
      • 管道的实现机制:RequestDelegate与ApplicationBuilder

    参考资源:

    https://www.cnblogs.com/artech/p/how-pipeline-is-built.html

    https://www.cnblogs.com/artech/p/asp-net-core-pipeline.html

     添加中间件的方法:

    //向应用程序的请求管道中添加一个内联定义的中间件委托
    //调用的方法:public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware);
    //命名空间:Microsoft.AspNetCore.Builder
    //类 static class UseExtensions

    app.Use(async (contex,next)=> { //await await next.Invoke(); });

    //命名空间:Microsoft.AspNetCore.Builder
    //接口类:public interface IApplicationBuilder
    //方法:IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
    //将中间件委托添加到应用程序的请求管道
    app.Use(next=> { return (context) => { return next(context); }; });
    //namespace Microsoft.AspNetCore.Builder
    //public static class MapExtensions
    //public static IApplicationBuilder Map(this IApplicationBuilder app, PathString pathMatch, Action<IApplicationBuilder> configuration);
    //基于给定请求路径的匹配分支请求管道。如果请求路径以给定路径开始,则执行分支
    //会启用一个新的taskApp[taskApp.Run()],作为另外一个环境运行了。不是特别复杂的业务,用不到这个方法
    app.Map("/task",taskApp=> { taskApp.Run( async (context) => { await context.Response;/// } ); });
    • 应用程序宿主环境信息和应用程序生存周期事件

    //IHostEnvironment 提供有关应用程序正在运行的宿主环境的信息
    //IHostApplicationLifetime
     向使用者通知应用程序生存期事件。
    public
    void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplicationLifetime lftime) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } lftime.ApplicationStarted.Register(() => { ///...启动事件 } ); lftime.ApplicationStopping.Register(() => { ///正在停止事件 } ); lftime.ApplicationStopped.Register(()=> { //停止事件 }); app.UseStaticFiles(); app.UseOrchardCore(); }
    •  RouttingMiddleware配置路由

    我们首先需要在Startup.cs文件中的ConfigureServices方法中进行路由依赖注入 services.AddRouting();

            //第一种方式
                app.UseRouter(builder=>builder.MapGet("actionfirst",async context =>{
                    await context.Response.WriteAsync("this is first action");
                }));
    
                //第二种方式
                RequestDelegate handler=context=>context.Response.WriteAsync("this is second action");
                var route=new Route(new RouteHandler(handler),"actionsecond",app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>());
                app.UseRouter(route);
    
                //第三种方式:不常用
                app.Map("/task",taskApp=>{
                    taskApp.Run(async context=>{
                        await context.Response.WriteAsync("this is a task");
                    });
                });
  • 相关阅读:
    环境变量
    多重继承
    参数检查(@property)
    限制属性绑定(__slots__)
    实例属性和类属性
    2017-11-28 中文编程语言之Z语言初尝试: ZLOGO 4
    2017-10-23 在各种编程语言中使用中文命名
    2017-11-27 汉化了十数个编译器的前辈的心得体会
    五行
    阴阳
  • 原文地址:https://www.cnblogs.com/gougou1981/p/12348860.html
Copyright © 2020-2023  润新知