Skip to content

Commit 31bcc29

Browse files
committed
episode 40
1 parent ac7472d commit 31bcc29

File tree

2 files changed

+299
-1
lines changed

2 files changed

+299
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
### 2023
1818

19-
**七月份**[第 039 期](docs/episode-039.md) | [第 038 期](docs/episode-038.md) :high_brightness:
19+
**八月份**[第 040 期](docs/episode-040.md) :high_brightness:
20+
21+
**七月份**[第 039 期](docs/episode-039.md) | [第 038 期](docs/episode-038.md)
2022

2123
**六月份**[第 037 期](docs/episode-037.md)
2224

docs/episode-040.md

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# .NET 每周分享第 40 期
2+
3+
## 卷首语
4+
5+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/5fb14b14-ed89-4445-b317-29e9494e9316)
6+
7+
今年 `.NET Conf` 日期已经确定下来,11 月 14 到 16 号,有下面几个重要的内容:
8+
9+
1. 拥抱 `.NET` 生态
10+
2. 一系列现场环节
11+
3. 内容需求提交
12+
4. 探索其他主题,比如云原生,Blazor, .NET MAUI 和智能化应用
13+
5. 颁奖
14+
6. 全球本地活动
15+
16+
## 行业资讯
17+
18+
1、[Nuget 包中 Microsoft 签名更新](https://devblogs.microsoft.com/nuget/microsoft-author-signing-certificate-update-2023/)
19+
20+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/21e56868-ad97-45e0-8e76-06add5498f03)
21+
22+
公开发行的 `Nuget` 包通常需要作者的证书来进行签名,使用者可以通过certififcate 的 thumbprint 来校验包的一致性。最近微软更新了使用的证书,相应的开发者需要在 `nuget.config` 中增加相应的证书 thumbprint.
23+
24+
25+
2、[Moq 中的恶意代码](https://github.com/moq/moq/issues/1372)
26+
27+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/66f7cfee-d384-417f-9389-c29068f7dde9)
28+
29+
`Moq` 是 .NET 社区中广泛使用的一个单元测试库。最近的版本(4.20)包含了一个 [SponsorLink](https://github.com/devlooped/SponsorLink) 包,它会在编译阶段扫描用户 `git` 账户下的信息,并且上传到服务端用来检查是否为 `Sponsor`。这个违反了很多国家和公司的隐私条款,因此在社区得到了广泛的讨论。幸运的是最新的版本已经移除了该功能。
30+
31+
3、[Visual Studio 支持文件比较](https://devblogs.microsoft.com/visualstudio/new-in-visual-studio-compare-files-with-solution-explorer/)
32+
33+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/0f1c345a-2789-4bb1-9746-ab405a35e713)
34+
35+
文件比较是一项日常开发过程中常见的工作,之前一般会借助命令行工具或者第三方软件来进行比较。最近 `Visual Studio` 引入文件比较的功能,它有两种方式
36+
1. 选择多个文件,然后在上下文菜单中选择比较
37+
2. 选择一个文件,然后在文件选择对话框中选择文件进行比较
38+
39+
## 文章推荐
40+
41+
1、[C# 中的 Feature Gate](https://github.com/microsoft/FeatureManagement-Dotnet)
42+
43+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/fcf179e3-aec5-44be-b055-00e675871aaf)
44+
45+
`Microsfot.FeatureManagement``Microsoft.FeatureManagement.AspNetCore` 是微软维护的 **Feature Gate** 功能的包,主要是借助 `IConfiguration` 接口来实现功能的开关。这样应用程序无需重新编译,部署或者重启来完成功能的打开和关闭。
46+
47+
48+
2、[C# 中 Class 和 Struct 比较](https://blog.ndepend.com/class-vs-struct-in-c-making-informed-choices/)
49+
50+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/1c00adee-7db2-4ed2-98c8-d735f9712c07)
51+
52+
C# 中关于 `Class``Struct` 的比较数不胜数,这边文章给了一个详细的比较
53+
54+
1. Performance 考虑
55+
2. 复杂对象使用 class
56+
3. 轻量级数据用 struct
57+
4. 避免可变 struct
58+
5. 注意过量拷贝
59+
6. 涉及接口使用 class
60+
7. 引用乐类型使用 class
61+
8. 避免嵌套 struct
62+
63+
3、[ASP.NET Core 中使用 ProblemDetail 的 Response](https://timdeschryver.dev/blog/translating-exceptions-into-problem-details-responses)
64+
65+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/c28b13f5-ee8d-4cc3-a7cf-e4b081764e2a)
66+
67+
在网络应用程序遇到一场的时候,我们通常会返回如下的 response.
68+
69+
```text
70+
HTTP/1.1 500 Internal Server Error
71+
Content-Length: 0
72+
Connection: close
73+
Date: Mon, 24 Jul 2023 13:52:12 GMT
74+
Server: Kestrel
75+
Alt-Svc: h3=":5099"; ma=86400
76+
```
77+
78+
这个做法的问题是我们无法知道具体的错误是什么。在 [RFC3986](https://datatracker.ietf.org/doc/html/rfc7807) 中确定使用 `Problem Details` 方式来组织异常。虽然这仍然处于草稿阶段,但是很多应用程序已经接受这个标准。
79+
`ASP.NET Core 8.0` 预览版中,也支持这样的处理操作
80+
81+
1. 首先添加 `IApplicationBuilder.UseExceptionHandler()` 拓展方法
82+
83+
```csharp
84+
builder.Services.AddProblemDetails();
85+
var app = builder.Build();
86+
app.UseStatusCodePages();
87+
app.UseExceptionHandler();
88+
```
89+
90+
2. 实现 `IExceptionHandler` 接口
91+
92+
```csharp
93+
public class ExceptionToProblemDetailsHandler : Microsoft.AspNetCore.Diagnostics.IExceptionHandler
94+
{
95+
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
96+
{
97+
httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
98+
await httpContext.Response.WriteAsJsonAsync(new ProblemDetails
99+
{
100+
Title = "An error occurred",
101+
Detail = exception.Message,
102+
Type = exception.GetType().Name,
103+
Status = (int)HttpStatusCode.BadRequest
104+
}, cancellationToken: cancellationToken);
105+
106+
return true;
107+
}
108+
}
109+
```
110+
111+
3. 注册实例对象
112+
113+
```csharp
114+
builder.Services.AddExceptionHandler<ExceptionToProblemDetailsHandler>();
115+
```
116+
117+
4、[Powershell 中 Foreach-Object 中 Parallel 参数](https://www.youtube.com/watch?v=w_4Slu19DcY&list=WL&index=1&t=1940s&ab_channel=JackedProgrammer)
118+
119+
`Powershell Core` 中的 `ForeEach-Object` 提供了 `-Parallel` 这个参数,该参数用来进行并发处理请求,提高效率。但是有几个注意点:
120+
121+
1. 并不是 `-Parallel` 就能完全提高运行效率
122+
2. 并行使用全局变量
123+
124+
```powershell
125+
$result = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
126+
127+
$logNames=@("Application", "System", "Windows PowerShell")
128+
$logNames | ForEach-Object -Parallel {
129+
$logs = Get-EventLog -LogName $_ -Newest 100
130+
$result = $using:result
131+
$result.AddRange($logs) | Out-Null
132+
}
133+
Write-Output $result.Count
134+
```
135+
136+
- `result` 类型包含 `Synchronized` 关键字
137+
- 在并行方法体中使用 `$using:result` 来获取全局变量
138+
139+
3. 并行调用定义方法
140+
141+
```powershelll
142+
function SayHello {
143+
Write-Output "hello"
144+
}
145+
146+
$funcDef = ${function:SayHello}.ToString()
147+
$array = 1..10
148+
$array | foreach-object -parallel {
149+
${function:SayHello} = $using:funcDef
150+
SayHello
151+
}
152+
```
153+
这里定义了 `SayHello` 方法,通过 `funcDef` 保存函数定义。然后在并行方法中使用 `$using:FuncDef` 来找到方法。
154+
155+
5、[Moq 迁移到 NSubstitue](https://timdeschryver.dev/blog/a-cheat-sheet-to-migrate-from-moq-to-nsubstitute#automate-migration)
156+
157+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/e3dc7f37-739c-4e21-9dfb-3103f484c2b1)
158+
159+
当上次 `Moq` 出现隐私问题之后,社区一直在鼓励大家迁移到 `NSubstitute`,这里有一份迁移清单。
160+
161+
6、[Unit Test 的建议](https://ardalis.com/mastering-unit-tests-dotnet-best-practices-naming-conventions/)
162+
163+
我们都知道单元测试的重要性,那么单元测试有哪些 Best Practice 呢 ?
164+
165+
- 清晰和可读性
166+
- 简单
167+
- 隔离
168+
- 可重复性
169+
- 快速
170+
- 可维护性
171+
- 覆盖率
172+
173+
那么单元测试命名规则
174+
- ClassNameMethodName.DoesXGivenY
175+
- Given_Precondition_When_Action_Then_ExpectedResult
176+
177+
7、[.NET SDK 装箱操作的优化](https://pvs-studio.com/en/blog/posts/csharp/1060/)
178+
179+
这是一篇 `.NET` SDK 在版本迭代中对装箱操作的优化,比如这样一段代码
180+
```csharp
181+
string Foo(int a)
182+
{
183+
return "The value is " + a;
184+
}
185+
```
186+
187+
一般而言,`+` 操作符的定义为 `string string.operator + (string leeft, object right)`,按照我们的理解,这里会发生一次装箱操作,因为 `a``int` 类型,而方法的接受的数据类型为 `object`,所以要进行装箱。而且 `IL` 代码也是同样如此
188+
```IL
189+
.method private hidebysig static void Foo(string str,
190+
int32 a) cil managed
191+
{
192+
....
193+
IL_0001: ldarg.0
194+
IL_0002: ldarg.1
195+
IL_0003: box [mscorlib]System.Int32
196+
IL_0008: call string [mscorlib]System.String::Concat(object,
197+
object)
198+
IL_000d: stloc.0
199+
IL_000e: ret
200+
}
201+
```
202+
203+
但是如果使用 `Visual Studio 2019` 编译这段代码,我们可以发现生成的 IL 代码却变成了这样
204+
205+
```IL
206+
.method private hidebysig static void Foo(string str,
207+
int32 a) cil managed
208+
{
209+
....
210+
IL_0001: ldarg.0
211+
IL_0002: ldarga.s a
212+
IL_0004: call instance string [mscorlib]System.Int32::ToString()
213+
IL_0009: call string [mscorlib]System.String::Concat(string,
214+
string)
215+
IL_000e: stloc.0
216+
IL_000f: ret
217+
}
218+
```
219+
220+
这样我们可以发现,这里没有装箱操作,只有 `Int32.ToString()` 方法。
221+
222+
## 开源项目
223+
224+
1、[Sisk](https://github.com/sisk-http/core)
225+
226+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/fb68eb93-9e8c-465b-8d44-771d8452575b)
227+
228+
`.NET` 生态中,`ASP.NET``ASP.NET Core` 占据了服务器端框架的主要市场,而且凭借优异的性能和官方支持背书,得到了广大用户的使用。但是有时候我们并不希望我们的服务端需要这么重量级的框架,那么可以选择 `Sisk` 这个开源包,它的目标就是一个轻量级,无依赖,简单易用的网络开发框架。
229+
230+
```csharp
231+
using Sisk.Core.Http;
232+
233+
using static Sisk.Core.Routing.RouteMethod;
234+
235+
var http = HttpServer.Emit(
236+
insecureHttpPort: 5000,
237+
host: out _,
238+
configuration: out _,
239+
router: out var router);
240+
241+
router.SetRoute(Get, "/", _ => new HttpResponse(200)
242+
{
243+
Content = new StringContent("Hello World")
244+
});
245+
246+
router.SetRoute(Get, "/hi/<name>", req =>
247+
{
248+
var name = req.Query["name"];
249+
return new(200)
250+
{
251+
Content = new HtmlContent($"<h1>Hello, {name}</h1>")
252+
};
253+
});
254+
255+
http.Start();
256+
Console.WriteLine($"Http server is listening on {http.ListeningPrefixes[0]}");
257+
Console.ReadKey();
258+
```
259+
260+
2、[NBomber](https://github.com/PragmaticFlow/NBomber)
261+
262+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/669ecec6-490f-4b10-bb40-02ed269f324e)
263+
264+
NBomber 是一个开源你的负载测试框架,比如 HTTP,WebSocket 等等。它的客户端逻辑全部由 `C#` 代码实现
265+
266+
```csharp
267+
var scenario = Scenario.Create("hello_world_scenario", async context =>
268+
{
269+
// you can define and execute any logic here,
270+
// for example: send http request, SQL query etc
271+
// NBomber will measure how much time it takes to execute your logic
272+
await Task.Delay(1_000);
273+
274+
return Response.Ok();
275+
})
276+
.WithLoadSimulations(
277+
Simulation.Inject(rate: 10,
278+
interval: TimeSpan.FromSeconds(1),
279+
during: TimeSpan.FromSeconds(30))
280+
);
281+
282+
NBomberRunner
283+
.RegisterScenarios(scenario)
284+
.Run();
285+
```
286+
287+
它有以下这点特点
288+
- 无任何协议的依赖
289+
- 无语义模型的依赖
290+
- 灵活的配置和简单的 API
291+
- 分布式集群支持
292+
- 实时报告
293+
- CI/CD 集成
294+
- 插件和拓展支持
295+
- 数据源支持
296+

0 commit comments

Comments
 (0)