.NET Core之详解项目结构的变化
一、前言
在.NET Framework或者.NET Core构建解决方案及项目的时候,通过官方提供的VS的IDE工具或者其他工具可以很机械化的创建各种类型的项目,至于解决方案解决,项目结构,及其项目结构的演变没有过多了解。这些是很基础的内容,平时通过.NET Core平台构建解决方案、项目的时候基本不关注,因为不会影响写业务代码,不会影响CURD,最近看了一篇相关的博客,很细致的描述了相关内容,所以自己动手实践一边,并且深入了解相关的内容。越是基础的内容,越需要去了解。
二、解决方案与项目
在dotnet core或者dotnet framework中,Console(控制台应用)是最基础的项目,创建一个控制台应用,编译,生成exe可执行文件,运行exe文件创建系统进程。解决方案与项目其相关定义、联系与区别如下内容:
.NET解决方案(Solution):在.NET中,解决方案是一个容器,用于组织和管理一个或多个相关的项目。一个解决方案文件(通常以.sln为扩展名)包含了对这些项目的引用以及它们之间的依赖关系。通过解决方案,开发者可以一次性打开、编译和部署多个相关的项目,从而提高了开发效率;解决方案通常用于包含一组协同工作的项目,例如一个Web应用程序可能包含一个Web项目、一个或多个类库项目(用于封装共享功能或业务逻辑)以及测试项目。这些项目可以相互依赖,通过解决方案进行统一的管理和构建。
.NET项目(Project):项目是构建特定软件组件(如类库、应用程序或Web服务)的配置和文件的集合。在.NET中,每个项目都包含源代码文件、资源文件、引用和构建配置等信息。项目定义了如何编译和生成输出(通常是DLL或EXE文件),以及这些输出如何与其他项目或组件进行交互;项目可以是独立的,也可以作为解决方案的一部分。在解决方案中,项目之间可以存在依赖关系,例如一个Web项目可能依赖于一个类库项目提供的服务或功能。项目还可以配置为使用特定的编程语言、框架或库,并定义编译选项、调试设置和部署目标等
联系与区别:解决方案和项目之间的关系是层级和依赖性的。一个解决方案可以包含多个项目(Console项目、Web项目、WPF项目、测试项目、类库项目、前端项目),而每个项目则专注于构建特定的软件组件。项目之间可以相互依赖,通过引用其他项目的输出或使用共享的代码和资源来协同工作。这种结构使得开发者能够更好地组织和管理复杂的开发任务,确保各个组件之间的正确集成和交互。在解决方案层级上进行构建、调试、部署的操作。
总结来说,.NET解决方案在物理上是一个容器,用于组织和管理相关的项目,在逻辑上是解决现实场景问题的总体方案;而项目则是构建特定软件组件的配置和文件集合或者各业务问题项目。它们共同构成了.NET开发环境的基础结构,帮助开发者有效地组织代码、资源和配置,提高开发效率和软件质量。
第一步、先创建一个解决方案,然后在解决方案中创建一个Console的项目,我们不使用VS工具,使用CLI来创建,新建一个文件夹作Demo为解决方案和项目的存储,然后在文件夹目录下运行CLI,输入dotnet new sln -n name命令创建一个解决方案,如下所示:
上述是关于按照了.NET环境提供的CLI相关的命令,然后在D盘创建demo文件夹下创建了名称为test的解决方案,使用文本编辑器可以查看解决方案的全局配置、项目、版本信息等内容,标识一个解决方案的元数据信息。
Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal
第二步、运行在demo文件夹下通过CLI运行命令dotnet new console -o consoleDemo,创建一个Console类型,名称为consoleDemo的项目,如下图所示:
上述文件夹中包含一个obj文件夹,.csproj的文件(项目元数据文件)、program.cs类库文件(启动类、及其方法),其中csproj文件描述项目的选择的.net框架,输出类型,全局配置参数项,如下图所示:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> </Project>
第三步、然后在demo文件夹下运行dotnet sln add consoleDemo/consoleDemo.csproj命令,将consoleDemo文件夹下的consoleDemo项目加入解决方案中,如下图所示:
使用VS工具打开解决方案,可以看到项目已经加入了解决方案,并且解决方案的.sln的加入这个项目的元数据信息,VS如下如所示:
namespace consoleDemo { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } }
通过上述步骤就已经完成了一个解决方案的创建,然后在解决方案中加入项目。在项目.csproj使用XML的格式定义项目项,OutputType告诉编译器编译后可直接执行的类型,TargetFramework定义项目的框架,比如在.net5.0/.net6.0/.net7.0等,program类是启动类,main方法是入口方法。
三、项目结构的变化
我们基于上述创建的是最基本项目console项目,要转换成Web项目,首先web项目是运行在主机上(webHost),所以要对项目文件.csproj进行调整,元数据描述项目是web项目,通过如下步骤所示:
第一步、.csproj文件改动如下,项目的sdk由Microsoft.NET.Sdk =>Microsoft.NET.Sdk.Web,删除OutputType类型,项目非直接执行而是跑在webhost上,完成上述操作,如图提示重新加载项目,会更新依赖框架加入Asp.netCore.App、项目中新增目录Properties,并且多一个文件launchSettings.json,这个web启动项配置文件,这样就完成由console项目转变成web项目,不过当前的web项目是只包含基本的文件依赖框架信息,必须提供Host供web加载。
第二步、 代码文件改动如下,①配置web主机,主要目的实现Http的支持,监听端口;设置Kestrol服务器为Web服务器(或者IIS、VS的Explorer);添加IIS的支持。在program的加入web主机,通过ConfigureWebHostDefaults进行创建,代码如下:
namespace consoleDemo { class Program { static void Main(string[] args) { Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { }) .Build() .Run(); } } }
②创建启动类,上述创建方法添加Http请求管道并注入我们需要的服务。而注入我们需要的服务使用Startup.cs类文件,代码如下:
1 2 3 4 5 6 | namespace demo { public class Startup { } } |
③在ConfigureWebHostDefaults方法中加入启动类Startup,使用这个启动类启动web应用,代码如下:
namespace consoleDemo { class Program { static void Main(string[] args) { Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) .Build() .Run(); } } }
④补齐Startup类内容,主要是两个应用,使用DI容器注入服务,就是相关类对象的注入(用于解耦组件(服务)之间的依赖关系);设置Http Request管道以插入中间件(模块化和可组合的方式构建应用程序,并在不同的请求处理阶段插入自定义的逻辑或功能。中间件是 ASP.NET Core 强大的特性之一,它提供了灵活且可扩展的方式来处理请求和响应),代码如下所示:
namespace consoleDemo { public class Startup { /// <summary> /// 注入服务 /// </summary> /// <param name="services"></param> public void ConfigureServices(IServiceCollection services) { } /// <summary> /// 插入中间件 /// </summary> /// <param name="app"></param> /// <param name="env"></param> public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { } } }
到此Web可以正常的启动,但是没有配置路由,请求返回信息,所以返回内容是空。
⑤给应用添加路由(传入Http请求与资源之间的映射),主要涉及两个中间UseRouting、UseEndpoints,在Startup类中加入中间件,并且定义简单请求与资源的映射关系,如下代码所示:
namespace consoleDemo { public class Startup { /// <summary> /// 注入服务 /// </summary> /// <param name="services"></param> public void ConfigureServices(IServiceCollection services) { } /// <summary> /// 插入中间件 /// </summary> /// <param name="app"></param> /// <param name="env"></param> 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"); }); }); } } }
PS:平时我们创建Web项目的Program类文件与我们当前的内容好像不一致,主要经过了加工整理的结果,提取主机的创建方法,然后在main方法中使用该方法创建一个主机,如下所示:
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>(); }); }
上述是一个最简单的Web项目,路由,资源映射返回请求结果,实践项目中会复杂的多,因此会使用如下几种项目结构(延伸的)创建项目。
①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(); }); } }
②WebApi应用,在ConfigureServices中注入AddControllers,在Configure添加MapControllers,如下代码所示:
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoint => { endpoint.MapControllers(); }); } }
③Razor应用,在ConfigureServices中注入AddRazorPages,在Configure添加MapRazorPages,如下代码所示:
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoint => { endpoint.MapRazorPages(); }); } }
四、总结
通过上述项目结构的学习,延伸出关于解决方案,项目,对于这些基础知识内容,在开发业务系统可能不太在意,通过VS工具按照步骤创建就OK,但是要知其所以然,才能更好使用这个工具和项目结构,才能更好理解为什么是这样子设计的,对整体项目结构有一个比较清晰的认识与演变过程。
参考:https://www.cnblogs.com/tiger-wang/p/14267942.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?