今年 .NET Conf
日期已经确定下来,11 月 14 到 16 号,有下面几个重要的内容:
- 拥抱
.NET
生态 - 一系列现场环节
- 内容需求提交
- 探索其他主题,比如云原生,Blazor, .NET MAUI 和智能化应用
- 颁奖
- 全球本地活动
公开发行的 Nuget
包通常需要作者的证书来进行签名,使用者可以通过certififcate 的 thumbprint 来校验包的一致性。最近微软更新了使用的证书,相应的开发者需要在 nuget.config
中增加相应的证书 thumbprint.
Moq
是 .NET 社区中广泛使用的一个单元测试库。最近的版本(4.20)包含了一个 SponsorLink 包,它会在编译阶段扫描用户 git
账户下的信息,并且上传到服务端用来检查是否为 Sponsor
。这个违反了很多国家和公司的隐私条款,因此在社区得到了广泛的讨论。幸运的是最新的版本已经移除了该功能。
文件比较是一项日常开发过程中常见的工作,之前一般会借助命令行工具或者第三方软件来进行比较。最近 Visual Studio
引入文件比较的功能,它有两种方式
- 选择多个文件,然后在上下文菜单中选择比较
- 选择一个文件,然后在文件选择对话框中选择文件进行比较
Microsfot.FeatureManagement
和 Microsoft.FeatureManagement.AspNetCore
是微软维护的 Feature Gate 功能的包,主要是借助 IConfiguration
接口来实现功能的开关。这样应用程序无需重新编译,部署或者重启来完成功能的打开和关闭。
C# 中关于 Class
和 Struct
的比较数不胜数,这边文章给了一个详细的比较
- Performance 考虑
- 复杂对象使用 class
- 轻量级数据用 struct
- 避免可变 struct
- 注意过量拷贝
- 涉及接口使用 class
- 引用乐类型使用 class
- 避免嵌套 struct
3、ASP.NET Core 中使用 ProblemDetail 的 Response
在网络应用程序遇到一场的时候,我们通常会返回如下的 response.
HTTP/1.1 500 Internal Server Error
Content-Length: 0
Connection: close
Date: Mon, 24 Jul 2023 13:52:12 GMT
Server: Kestrel
Alt-Svc: h3=":5099"; ma=86400
这个做法的问题是我们无法知道具体的错误是什么。在 RFC3986 中确定使用 Problem Details
方式来组织异常。虽然这仍然处于草稿阶段,但是很多应用程序已经接受这个标准。
在 ASP.NET Core 8.0
预览版中,也支持这样的处理操作
- 首先添加
IApplicationBuilder.UseExceptionHandler()
拓展方法
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseStatusCodePages();
app.UseExceptionHandler();
- 实现
IExceptionHandler
接口
public class ExceptionToProblemDetailsHandler : Microsoft.AspNetCore.Diagnostics.IExceptionHandler
{
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await httpContext.Response.WriteAsJsonAsync(new ProblemDetails
{
Title = "An error occurred",
Detail = exception.Message,
Type = exception.GetType().Name,
Status = (int)HttpStatusCode.BadRequest
}, cancellationToken: cancellationToken);
return true;
}
}
- 注册实例对象
builder.Services.AddExceptionHandler<ExceptionToProblemDetailsHandler>();
4、Powershell 中 Foreach-Object 中 Parallel 参数
在 Powershell Core
中的 ForeEach-Object
提供了 -Parallel
这个参数,该参数用来进行并发处理请求,提高效率。但是有几个注意点:
- 并不是
-Parallel
就能完全提高运行效率 - 并行使用全局变量
$result = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
$logNames=@("Application", "System", "Windows PowerShell")
$logNames | ForEach-Object -Parallel {
$logs = Get-EventLog -LogName $_ -Newest 100
$result = $using:result
$result.AddRange($logs) | Out-Null
}
Write-Output $result.Count
result
类型包含Synchronized
关键字- 在并行方法体中使用
$using:result
来获取全局变量
- 并行调用定义方法
function SayHello {
Write-Output "hello"
}
$funcDef = ${function:SayHello}.ToString()
$array = 1..10
$array | foreach-object -parallel {
${function:SayHello} = $using:funcDef
SayHello
}
这里定义了 SayHello
方法,通过 funcDef
保存函数定义。然后在并行方法中使用 $using:FuncDef
来找到方法。
当上次 Moq
出现隐私问题之后,社区一直在鼓励大家迁移到 NSubstitute
,这里有一份迁移清单。
我们都知道单元测试的重要性,那么单元测试有哪些 Best Practice 呢 ?
- 清晰和可读性
- 简单
- 隔离
- 可重复性
- 快速
- 可维护性
- 覆盖率
那么单元测试命名规则
- ClassNameMethodName.DoesXGivenY
- Given_Precondition_When_Action_Then_ExpectedResult
这是一篇 .NET
SDK 在版本迭代中对装箱操作的优化,比如这样一段代码
string Foo(int a)
{
return "The value is " + a;
}
一般而言,+
操作符的定义为 string string.operator + (string leeft, object right)
,按照我们的理解,这里会发生一次装箱操作,因为 a
为 int
类型,而方法的接受的数据类型为 object
,所以要进行装箱。而且 IL
代码也是同样如此
.method private hidebysig static void Foo(string str,
int32 a) cil managed
{
....
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: box [mscorlib]System.Int32
IL_0008: call string [mscorlib]System.String::Concat(object,
object)
IL_000d: stloc.0
IL_000e: ret
}
但是如果使用 Visual Studio 2019
编译这段代码,我们可以发现生成的 IL 代码却变成了这样
.method private hidebysig static void Foo(string str,
int32 a) cil managed
{
....
IL_0001: ldarg.0
IL_0002: ldarga.s a
IL_0004: call instance string [mscorlib]System.Int32::ToString()
IL_0009: call string [mscorlib]System.String::Concat(string,
string)
IL_000e: stloc.0
IL_000f: ret
}
这样我们可以发现,这里没有装箱操作,只有 Int32.ToString()
方法。
1、Sisk
在 .NET
生态中,ASP.NET
和 ASP.NET Core
占据了服务器端框架的主要市场,而且凭借优异的性能和官方支持背书,得到了广大用户的使用。但是有时候我们并不希望我们的服务端需要这么重量级的框架,那么可以选择 Sisk
这个开源包,它的目标就是一个轻量级,无依赖,简单易用的网络开发框架。
using Sisk.Core.Http;
using static Sisk.Core.Routing.RouteMethod;
var http = HttpServer.Emit(
insecureHttpPort: 5000,
host: out _,
configuration: out _,
router: out var router);
router.SetRoute(Get, "/", _ => new HttpResponse(200)
{
Content = new StringContent("Hello World")
});
router.SetRoute(Get, "/hi/<name>", req =>
{
var name = req.Query["name"];
return new(200)
{
Content = new HtmlContent($"<h1>Hello, {name}</h1>")
};
});
http.Start();
Console.WriteLine($"Http server is listening on {http.ListeningPrefixes[0]}");
Console.ReadKey();
2、NBomber
NBomber 是一个开源你的负载测试框架,比如 HTTP,WebSocket 等等。它的客户端逻辑全部由 C#
代码实现
var scenario = Scenario.Create("hello_world_scenario", async context =>
{
// you can define and execute any logic here,
// for example: send http request, SQL query etc
// NBomber will measure how much time it takes to execute your logic
await Task.Delay(1_000);
return Response.Ok();
})
.WithLoadSimulations(
Simulation.Inject(rate: 10,
interval: TimeSpan.FromSeconds(1),
during: TimeSpan.FromSeconds(30))
);
NBomberRunner
.RegisterScenarios(scenario)
.Run();
它有以下这点特点
- 无任何协议的依赖
- 无语义模型的依赖
- 灵活的配置和简单的 API
- 分布式集群支持
- 实时报告
- CI/CD 集成
- 插件和拓展支持
- 数据源支持