• 深入浅出Dotnet Core的项目结构变化


    有时候,越是基础的东西,越是有人不明白。

    前几天Review一个项目的代码,发现非常基础的内容,也会有人理解出错。

    今天,就着这个点,写一下Dotnet Core的主要类型的项目结构,以及之间的转换和演化。

    一、最基础的应用Console

    控制台应用,是Dotnet Core乃至前边的Dotnet Framework中,最基础的项目。

    我们来创建一个Console项目看一下:

    % dotnet new console -o demo
    

    创建完成后,打开工程。工程里只有一个文件Program.cs,里面只有一个方法Main

    namespace demo
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
            }
        }
    }
    

    在Dotnet Core所有类型的项目中,Program.cs都是最开始的入口,main方法,也是最开始的入口方法。

    这个工程中,还有一个文件也需要了解一下,demo.csproj,这是这个项目的定义文件:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
      </PropertyGroup>
    
    </Project>
    

    这里面,OutputType告诉编辑器这个工程编译后可以直接执行,TargetFramework定义运行的框架。

    注意,这个框架字串有个对照表:net5.0对应的是.Net 5.0;如果你想用Dotnet Core 3.1,对应的字符串是netcoreapp3.1,而不是net3.1。准确的说,3.1是.Net Core 3.1,而5.0是.Net 5.0。不用太纠结,微软的命名规则而已。

        为了防止不提供原网址的转载,特在这里加上原文链接:https://www.cnblogs.com/tiger-wang/p/14267942.html

    这就是控制台应用Console的初始状态。

    下面,我们看看这个工程如何转变为Web应用。

    二、转为Web应用

    第一件事,我们需要改动demo.csproj项目定义文件。

    Web应用跑在WebHost上面,而不是从直接执行。所以,我们需要把OutputType项去掉。

    另外,SDK也需要改一下。Console我们用的是Microsoft.NET.Sdk,Web应用要改成Microsoft.NET.Sdk.Web

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>net5.0</TargetFramework>
      </PropertyGroup>
    
    </Project>
    

    改完保存。

    这时候,应该可以注意到,项目的发生了变化:

    • 依赖的框架从Microsoft.NETCore.App变成了两个,多了一个Microsoft.AspNetCore.App,表明现在这是一个Asp.net Core的应用;
    • 项目中自动生成了一个目录Properties,下面多了一个文件launchSettings.json。这个文件大家应该很熟悉,就不解释了。

    这时候,应用已经从Console转为了Web应用。

    Asp.Net Core框架提供了Host供Web加载。我们需要做的,是把Host构建器加到程序中。通常,我们需要两个构建器:

    • 通用主机 Generic host builder
    • Web主机 Web host builder

    1. 配置通用主机

    通用主机在Microsoft.Extensions.Hosting.Host中,主要给Web应用提供以下功能:

    • 依赖注入
    • 日志
    • 配置 IConfiguration
    • IHostedService实现

    加入通用主机很简单,就一个方法CreateDefaultBuilder

    class Program
    {
        static void Main(string[] args)
        {
            Host.CreateDefaultBuilder(args)
                .Build()
                .Run();
        }
    }
    

    2. 配置Web主机

    Web主机才是真正与Web相关的内容,主要实现:

    • Http支持
    • 设置Kestrol服务器为Web服务器
    • 添加IIS支持

    加入Web主机,也是一个方法ConfigureWebHostDefaults

    class Program
    {
        static void Main(string[] args)
        {
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                })
                .Build()
                .Run();
        }
    }
    

    这个方法用来添加Http请求管道并注入我们需要的服务。而注入我们需要的服务,就是我们最常见的Startup.cs的内容。

    下面,我们先创建Startup.cs

    namespace demo
    {
        public class Startup
        {
        }
    }
    

    在前边ConfigureWebHostDefaults中,加入Startup,并补齐代码:

    class Program
    {
        static void Main(string[] args)
        {
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
                .Build()
                .Run();
        }
    }
    

    这就是Program.cs中的完整代码了。整理一下,就是我们常见的样子:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
    

    不过,到这儿还不能正常运行,因为Startup.cs现在还是空的。

    3. 补齐Startup类

    Startup类在Asp.net Core应用中有着重要的作用。这个类用于:

    • 使用DI容器注入服务
    • 设置Http Request管道以插入中间件

    下面我们补齐所需的方法:

    namespace demo
    {
        public class Startup
        {
            public void ConfigureServices(IServiceCollection services)
            {
            }
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
            }
        }
    }
    

    运行,到这儿,Web应用已经可以正常启动了。

    4. 给应用添加路由

    Web应用启动了,但里面什么也没有,是空的。

    要访问Web应用中的任何资源,需要配置路由。这儿的路由,基本上就是传入Http请求与资源之间的映射。

    我们可以用下面的中间件来启动路由:

    • UseRouting
    • UseEndpoints

    加一下试试:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
        app.UseEndpoints(endpoint => {
            endpoint.MapGet("/", async context =>
            {
                await context.Response.WriteAsync("Hello from Demo");
            });
        });
    }
    

    这次运行,浏览器中就看到正确的输出了。

    我们可以用MapGet映射更多资源:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
        app.UseEndpoints(endpoint =>
        {
            endpoint.MapGet("/", async context =>
            {
                await context.Response.WriteAsync("Hello from Demo");
            });
            endpoint.MapGet("/test", async context =>
            {
                await context.Response.WriteAsync("Hello from Demo.Test");
            });
            endpoint.MapGet("/about", async context =>
            {
                await context.Response.WriteAsync("Hello from Demo.About");
            });
        });
    }
    

    到这儿,我们成功地把Console应用转为了Web应用。

    三、延伸内容

    上面完成的Web应用,算是Web应用中的基础。基于这个内容,我们还可以扩展到别的项目结构。

    1. 改为MVC应用

    需要在ConfigureServices 中注入AddControllersWithViews,并在Configure中添加MapDefaultControllerRoute

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoint =>
            {
                endpoint.MapDefaultControllerRoute();
            });
        }
    }
    

    2. 改为WebAPI应用

    需要注入AddControllersMapControllers

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoint =>
            {
                endpoint.MapControllers();
            });
        }
    }
    

    3. 改为Razor应用

    需要注入AddRazorPagesMapRazorPages

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoint =>
            {
                endpoint.MapRazorPages();
            });
        }
    }
    
    

    四、总结

    看下来,其实过程很简单。通过这种方式,能更进一步理解Dotnet Core的项目结构以及应用的运行过程。

    希望对大家能有所帮助。

    本文的配套代码在:https://github.com/humornif/Demo-Code/tree/master/0038/demo

    微信公众号:老王Plus

    扫描二维码,关注个人公众号,可以第一时间得到最新的个人文章和内容推送

    本文版权归作者所有,转载请保留此声明和原文链接

  • 相关阅读:
    日期类型存储方法
    Log4j2的一些记录
    【Maven】学习记录
    HTML 图片加载问题
    浏览器的组成
    javascript数组的实例属性(方法)
    javascript数组的内置对象Array
    javascript之this
    css的position,float属性的理解
    简单介绍帧动画
  • 原文地址:https://www.cnblogs.com/tiger-wang/p/14267942.html
Copyright © 2020-2023  润新知