我们的大部分开发工作都是在 Visual Studio
中完成,当我们在自己的分支上完成工作,就需要登录到 GitHUB
或者 Azure DevOps
上创建 PR。在新的 Visual Studio
中,我们就可直接在 Visual Studio
中直接创建 PR。 基本流程是这样的
- 创建新的分支
- 提交和推送分支
- 创建 PR
- 修改并更新 PR
1、qodana
JetBrains 为 .NET
应用程序的代码质量推出了一个工具叫做 qodana for .NET
,它既可以集成到 CI
工具中,也可以在本地执行,并且生成网页版本的质量报告。
GUID
是一个 128 bit 组成的值,用来减少冲突。在 C#
中 GUID 有以下几个特征
- 它是一个值类型,所以默认值为
00000000-0000-0000-0000-000000000000
, 也等于Guid.Empty
- 随机创建 GUID 的方式是
GUID.Empty
- 它的
ToString
方式有多种:
var inputGuid = Guid.NewGuid();
Console.WriteLine(inputGuid.ToString()); // 081bdc64-b126-4ac4-a1a5-96d41c8622fc
Console.WriteLine(inputGuid.ToString("D")); //081bdc64-b126-4ac4-a1a5-96d41c8622fc
Console.WriteLine(inputGuid.ToString("N")); // 081bdc64b1264ac4a1a596d41c8622fc
Console.WriteLine(inputGuid.ToString("B")); // {081bdc64-b126-4ac4-a1a5-96d41c8622fc}
Console.WriteLine(inputGuid.ToString("P")); //(081bdc64-b126-4ac4-a1a5-96d41c8622fc)
Scott Sauber 是 Microsoft MVP
, 他分享了他关于 .NET
应用程序的原则
- 在
ASP.NET Core
中使用功能的方式组织文件夹 - 将
Warning
当作Error
, 在csproj
文件中这么配置
<propertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</propertyGroup>
- 正确使用日志
- 使用
FallbackPolicy
全局使用Authorize
标注 - 删除
Asp.NET Core
的 Server Header - 不要使用
IOption
作为依赖注入的选项,使用具体的值 Endpoint
要版本化- 结构化方法,比如正确的结果在方法的最后,使用
return
而不是if-else
- 注意
HTTP
安全方面的控制 - 构建一次到处部署
在过去的 Visual Studio
中,在添加新的文件的时候,通常会弹出上面的窗口,它会展示所有的已经安装的模板。在新版的 Visual Studio
中,我们可以使用更加简单的对话框,在这里就直接直接输入文件的名字,Visual Studio 会根据模板创建相应的文件,而且也支持多个文件,文件夹的创建。
4、ASP.NET Core WebSocket 客户端服务端通信
ASP.NET Core
支持 WebSocket
开发,这篇文章展示了如果使用 WebSocket
实现一个简单的聊天室功能。
我们都知道在 C#
中, StringBuilder
在字符串处理方面比 string
操作更加高效,通常是发生在字符串拼接的使用场景中。但是在 Replace
的操作中,StringBuilder
的效率也是比 String
效率高。
Dictionary<string, string> _opMapper = new()
{
{"×", "*"},
{"÷", "/"},
{"SIN", "Sin"},
{"COS", "Cos"},
};
var retString = new StringBuilder(inputString);
foreach (var key in _opMapper.Keys)
{
retString.Replace(key, _opMapper[key]);
}
return retString.ToString();
当我们在浏览 Nuget
包的时候,通常希望有一个精美的 README
文件来描述这个包,并且包含丰富的文档链接。那么在 csproj
文件中包含整个就可以了。
<PropertyGroup>
<PackageIcon>icon.png</PackageIcon>
<RepositoryUrl>https://github.com/khalidabuhakmeh/Htmx.Net</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!-- IMPORTANT Do not forget this -->
<PackageReadmeFile>README.md</PackageReadmeFile>
<Description>
Adds ASP.NET Core tag helpers to make generating urls for Htmx (https://htmx.org) easier. Mimics the ASP.NET Core url tag helpers.
</Description>
</PropertyGroup>
关于 Logging
, Nick
在 NDC 大会上分享他的原则:
- 日志中的
message
参数其实是模板 - 使用结构化日志并且给参数合适的名字
- 不在模板中使用字符串拼接的方式
- 对于
inactive
的日志级别,避免装箱操作 - 考虑使用
Source Generated
的日志 - 不要尝试比工具更加聪明
- 考虑使用
Warning
作为默认级别 - 日志只记录讲好一个故事的必要信息
当我们在使用 C#
对网页 HTML
元素进行解析,通常我们会采取类型字符串正则匹配的方式,这样做太繁琐了。HTMLAgilityPack
包可以然我们类似 HTML
元素选择的方式获取想要的结果。
var html = @"http://html-agility-pack.net/";
HtmlWeb web = new HtmlWeb();
var htmlDoc = web.Load(html);
var node = htmlDoc.DocumentNode.SelectSingleNode("//head/title");
Console.WriteLine("Node Name: " + node.Name + "\n" + node.OuterHtml);
AutoFixture 是一个单元测试辅助开发库,用来帮助我们开发的单元测试库只关心我们需要测试的内容,而不需要被其他的修改而影响。
假设我们现在有一个 Employee
的类
public class Employee
{
public Employee(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; set; }
public string LastName {get; set;}
public string FullName => $"{FirstName} {LastName}";
}
我们的单元测试是这样的
public void FullName_Return_Expected()
{
var sut = new Employee("feng", "gao");
var actual = sut.FullName;
Assert.Equal("feng gao", actual);
}
这个单元测试没有问题,如果我们的 Employee
的构造函数被修改成这样
- public Employee(string firstName, string lastName)
+ public Employee(string firstName, string lastName, int employeeNumber)
毫无疑问,我们之前的单元测试肯定失败,甚至无法编译。这时候我们的 AutoFixture
起作用的的
public void FullName_Return_Expected()
{
var fixture = new Fixture();
var sut = fixture.Build<Employee>().With(a => a.FirstName, "feng")
.With(a => a.LastName, "gao").Create();
var actual = sut.FullName;
Assert.Equal("feng gao", actual);
}