大家假期好,好久不见,之前忙于其他事情,公众号暂时搁置了一个月了,新的一年开始了,很多小伙伴开始催更了,粉丝的要求必须满足。
2022年打算重点推广BCVP社区,所以还是希望有愿意投稿的小伙伴,积极投稿哟。同时我也有以下几个打算,欢迎广而告之:
1、还是有很多小伙伴对Blog.Core的学习内容和技术知识不是很清晰,所以打算每月开一个直播,主要是以直播公开课的形式分享里边的知识架构(B站直播);
2、同时也把之前欠的技术难点给补充上,比如GitHub上说的最多的就是部门数据的权限功能(开发中)、数据迁移优化和项目完全升级为.NET6.0(本文所讲);
3、继续讲讲微服务相关的内容(B站视频录播);
以上三个知识点会慢慢铺开来进行,也欢迎更多的小伙伴公司使用Blog.Core,如果公司有使用,可得老张技术指导。
老张
https://github.com/anjoy8/Blog.Core/issues/75
废话不多说,直接开始今天的内容分享。
需求说明
ASP.NET6.0正式版已经出来了半年多了,作为一个LTS版本,也是受到官方的强烈推荐和升级建议,自然,作为有3.7k个Star的Blog.Core已经在第一时间更新了6.0,并且一直健壮的运行了很久了,只不过遗留了一个功能点:6.0版本优化了Program.cs的写法,并把Startup.cs给优化掉了,看上去是一个Mini精简版本——采用新的宿主模型。
最小宿主模型:
1)、大大减少了创建应用程序所需的文件和代码行数。只有一个文件需要四行代码。同时也新增特性最小API模型。
2)、Startup.cs将和 Program.cs 合并到单个 Program.cs 文件中。
3)、使用顶级语句减少应用程序所需的代码。
4)、使用全局 using 指令消除或最大程度地减少所需的 using 语句行数。
不过很多小伙伴表示看着别扭和不太习惯,同时我也考虑到我的博客中,都是老的版本,就一直没升级,不过昨天也是尝试了一波,表示改写起来也是比较简单的。
相关的代码已经提交到了GitHub上的mini-program分支,如果大家一周内没问题,我会merge到master分支,欢迎大家clone代码尝试,如果有错误欢迎提issue,如果有其他疑问和建议也欢迎提issue,我会帮助解答。
过程很简单,这里列举下有哪些问题点。
1、使用隐式命名空间引用
如果我们创建一个空的.net6.0webapi项目,可以看到program.cs内容是这样的:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
这里是没有using命名空间的,但是如果我们在类和方法上点击F12,也能看到具体的程序集。同时也没有定义具体的类名和方法名,所以才导致很多小伙伴表示看着比较别扭。
如何实现的呢,就是在.csproj文件里,启动隐式命名空间引用即可:
<ImplicitUsings>enable</ImplicitUsings>
打开obj目录(用于存放编译过程中生成的中间临时文件),在cs文件的对应目录发现了WebApplication1.GlobalUsings.g.cs文件:
虽然看着别扭,但是整体其实也能看的明白,还是定义host、注册服务和配置中间件这三个步骤,两个核心关键点就是.build()完后,容器里才会注册具体的服务实例,.run()完后,项目就正式的启动起来了。
咱们把官方给的写法拷贝到Blog.Core中,就可以改造了。
同时要注意另一个null的配置,如果配置了在controller的action中,会校验空值的,必须传参,所以我的建议还是不开启:
<Nullable>enable</Nullable>
2、配置自定义注入容器
首先说下以官方容器为默认容器,是如何做依赖注入服务注册的,和之前很像:
builder.Services.AddScoped<UseServiceDIAttribute>();
builder.Services.AddSingleton(new Appsettings(builder.Configuration));
用的是builder.Services来处理,将之前的service前边,统一加上builder即可。
当然咱们也用到Autofac,所以需要配置自定义的注入容器:
builder.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule(new AutofacModuleRegister());
builder.RegisterModule<AutofacPropertityModuleReg>();
})
其他的日志配置和app参数配置和之前一样,具体参考Blog.Core代码即可。
3、如何使用配置和环境参数
在第一步中,已经生成了builder,官方已经给我们做好了处理,所以直接作为属性拿来用即可:
4、中间件什么时候开始?
上边的过程是准备阶段,我们把builder.build()后,构建完成,开始配置中间件管道了。
// 3、配置中间件
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
//app.UseHsts();
}
app.UseIpLimitMiddle();
app.UseRequestResponseLogMiddle();
app.UseRecordAccessLogsMiddle();
app.UseSignalRSendMiddle();
app.UseIpLogMiddle();
app.UseAllServicesMiddle(builder.Services);
// and so on...
其他的也直接copy过来就行。
5、中间件使用依赖注入服务
在之前的写法中,我们中间件可以作为一个类似构造函数那样,将接口注册,但是现在没有这些东西了,从哪里获取服务呢,比如我们开启QuarzNet任务,可以用原生的写法,从容器ServiceProvider中获取:
var tasksQzServices = scope.ServiceProvider.GetRequiredService<ITasksQzServices>();
var schedulerCenter = scope.ServiceProvider.GetRequiredService<ISchedulerCenter>();
app.UseSeedDataMiddle(myContext, builder.Environment.WebRootPath);
app.UseQuartzJobMiddleware(tasksQzServices, schedulerCenter);
改到这里就没有什么了,直接执行.run()方法就行了。
6、其他需要注意的点
1、Swagger自定义html的Stream
因为Program类的原因,不能直接用this.GetType()了,可以换这种写法:
Assembly.GetExecutingAssembly()
.GetManifestResourceStream("Blog.Core.Api.index.html")
2、其他调用Program.cs
Program使用最小宿主模式后,在其他类库里会访问受限,所以要换成其他的
其他的还没有遇到有需要更新的,Blog.Core也是比较全的项目了,基本涵盖了平时大家开发的功能,当然,如果有自己把握不住的,欢迎GitHub上提issue。