咱们很快乐地发表 .NET Community Toolkit 8.1 版正式公布!这个新版本包含呼声很高的新性能、bug 修复和对 MVVM 工具包源代码生成器的大量性能改良,使开发人员在应用它们时的用户体验比以往更好!
就像在咱们之前的版本中一样,咱们非常感谢 Microsoft 应用该工具包的团队以及社区中的其余开发人员收到的所有反馈,这些反馈曾经并将持续对咱们如何设计所有新性能和改良并确定其优先级产生微小影响。咱们非常感谢每一位做出奉献并一直帮忙 .NET Community Toolkit 变得更好的人!
.NET 社区工具包中有什么?
正如咱们在之前的布告帖子中所做的那样,让咱们首先简要回顾一下 .NET Community Toolkit 蕴含的内容。它由几个独立的库组成:
- CommunityToolkit.Common
- CommunityToolkit.Mvvm (又名“Microsoft MVVM Toolkit”)
- CommunityToolkit.Diagnostics
- CommunityToolkit.HighPerformance
这些库还宽泛用于 Windows 附带的多个收件箱应用程序,例如 Microsoft Store 和照片应用程序!
无关 .NET Community Toolkit 历史的更多详细信息,请拜访咱们之前的 8.0.0 布告帖子的链接。
以下是 .NET Community Toolkit 新 8.1 版中蕴含的次要更改的局部。
自定义属性 [ObservableProperty]
正如咱们在 8.1.0 预览版 1 布告博客文章中提到的,对于 MVVM 工具包源代码生成器,咱们最须要的性能之一(请参阅 #208、#217、#228)是反对对 [ObservableProperty] 应用自定义属性。有几个提议的设计来反对这一点,咱们最终决定利用 C# 中的现有语法“property”: 来让开发人员标记属性以流传到生成的属性。有几个劣势:
- 它利用内置的 C# 语法,使该性能感觉“原生”并且不须要额定的属性
- 它解决了注解属性只能针对属性,不能针对字段的问题
也就是说,应用 MVVM Toolkit 8.1,当初反对以下场景:
[ObservableProperty]
[property: JsonPropertyName("responseName")]
[property: JsonRequired]
private string? _name;
这将在幕后生成以下属性:
[JsonPropertyName("responseName")]
[JsonRequired]
public string? Name
{
get => _name;
set
{if (!EqualityComparer<string?>.Default.Equals(_name, value))
{OnPropertyChanging("Name");
OnNameChanging(value);
_name = value;
OnPropertyChanged("Name");
OnNameChanged(value);
}
}
}
partial void OnNameChanging(string? value);
partial void OnNameChanged(string? value);
能够看到生成的属性有咱们指定的两个属性!这容许齐全灵便地为生成的属性增加正文,同时应用内置的 C# 语法并且对该性能反对的属性类型没有限度。
留神:生成的代码略有不同,包含此处未显示的其余性能优化。
您能够在链接找到咱们对于新源代码生成器的所有文档。
MVVM 工具包分析器
此版本的 MVVM 工具包也是第一个引入专用分析器的版本。它可能帮忙开发人员以最佳形式应用 MVVM 工具包。也就是说,MVVM 工具包将不再只是针对应用谬误的性能收回诊断(例如,以报错的形式),它当初还会显示改良代码和防止常见谬误的倡议!
第一个分析器涵盖了应用 [ObservableProperty] 属性时的一个常见谬误。参照这个例子:
[ObservableProperty]
private string? name;
[RelayCommand]
public async Task LoadUserAsync()
{User user = await _userService.FetchUserAsync();
name = user.Name; // Whoops! Assigning to the field!
}
开发人员不小心调配给一个字段(而不是生成的属性),而后被卡在 UI 上。UI 上没有显示该更改,也没有明确阐明为什么会这样,这一情景曾经被屡次提出。新的分析器将在这些状况下提供帮忙,它将标记反对可察看属性的字段的所有赋值,并显示诊断倡议援用生成的属性。你不会再收到莫名其妙的属性失落的告诉。
第二个新分析器旨在帮忙缩小应用 MVVM 工具包的应用程序中的二进制文件大小。正如咱们在 8.0.0 布告帖子中提到的,MVVM 工具包蕴含多个属性(例如[ObservableObject]),这些属性容许生成器将实现 INotifyPropertyChanged 和 INotifyPropertyChanging 接口所需的所有代码(也可抉择应用其余帮忙程序)注入现有类。
这仅实用于无奈继承的状况:如果您不属于这种状况,您应该抉择继承 ObservableObject,从而减小的二进制文件大小,因为编译器不用在每个过程中一遍又一遍地复制那些雷同的助手类型。请参阅这个例子:
[ObservableObject]
public partial class MyViewModel
{[ObservableProperty]
private string? name;
}
这里,MyViewModel 不是从任何类型继承而来,因而它应该继承 ObservableObject 而不是应用 [ObservableObject] 属性,以此改良二进制大小。新的分析器将标记所有与此类似的场景并倡议改用继承。这将特地有助于初学者,他们可能不理解两种不同办法的细微差别并且可能不晓得如何抉择。在这些状况下,当初分析器能够提供帮忙。
MVVM 工具包源代码生成器优化
正如咱们提到的,这个新版本还包含对 MVVM 工具包的次要性能优化,以进一步改善开发人员的用户体验,尤其是优化了开发人员在解决十分大的解决方案时的体验。咱们花了很多工夫改良咱们所有生成器的架构,并与 Roslyn 团队的工程师交谈,以确保咱们正在尽可能地施展它们的性能。
以下只是咱们在这方面所做的一部分改良:
- 为 Roslyn 4.3 增加了多指标(#428,#462):如果反对,MVVM 工具包源代码生成器当初将应用 Roslyn 4.3 指标,这样他们就能够在主机反对的状况下抉择退出一些更优化的 API。这一性能在援用 MVVM 工具包时会主动启用。
- 应用 ForAttributeWithMetadataName<T>(#436):咱们将生成器切换到新的高级 Roslyn API 以匹配属性,这大大提高了生成器触发特定属性的性能。比方当初 [ObservableProperty] 就在用这个。
- 将诊断移入诊断分析器(#433,#434):咱们将简直所有诊断都挪动到诊断分析器,这些诊断分析器在过程外运行并且独立于源生成器。这样可能显著缩小键入时的 overhead,因为所有诊断逻辑当初都在独自的过程中运行,并且不会升高 IntelliSense 的速度。
- 进行在增量提供程序中应用符号(#435):咱们更新了所有增量提供程序以不再流传符号。这能够缩小内存应用,因为流传符号会导致 Roslyn 不必要地根编译对象。
- 更多性能优化(#447、#460、#469、#487、#489):咱们彻底查看了所有增量模型和增量管道,以显著进步性能并缩小内存调配。
IObservable<T> 信使扩大
另一个性能需要,尤其是由那些在应用程序中大量应用响应式 API 开发人员提出,是寻求一种办法来桥接 MVVM 工具包中的性能。界面的新扩大 IObservable<T> extensions 当初反对此性能。它们能够按如下形式应用:
IObservable<MyMessage> observable = Messenger.CreateObservable<MyMessage>();
就像这样!此扩大将创立一个对象 IObservable<T>,该对象可用于订阅音讯并对其做出动静反馈。还反对通过独自的重载指定不同的标记。这面这个示例展现了新 API 的端到端应用:
var token =
Messenger
.CreateObservable<MyMessage>()
.Where(...)
.Subscribe(m => Console.WriteLine($"Hello {m.Username}!"));
.NET 7 和 C# 11 反对
.NET Community Toolkit 工具包的新公布版本还将 .NET 7 TFM 增加到高性能包中,新版本中还包含一些变动,次要对新的 C# 11 语言性能进行了改善,比方 ref fields 就是一个典型。
以下类型当初不再处于预览状态,以及更新应用了新的 ref 平安规定:
- Ref<T>
- ReadOnlyRef<T>
- NullableRef<T>
- ReadOnlyNullableRef<T>
上面这种场景能够应用这些规定:
public static bool TryGetElementRef(out NullableRef<T> reference)
{// Logic here...}
也就是说,应用 NullableRef<T> 类型规定能够无效地让办法具备 out ref T 参数, 而这在 C# 中是无奈通过表达式做到的. 咱们还打算扩大这些类型的 API 浅层面,从而容许这些类型通过应用 Unsafe 类型,提供一种易于应用的代替 GC-ref 算法的办法,这在视觉上也更相似于传统的指针算法。
此外,所有不在预览模式中的 ref struct 类型都已被更新,应用外部的 ref 字段实现更好的性能。这些类型包含:
- Span2D<T>
- ReadOnlySpan2D<T>
- RefEnumerable<T>
- ReadOnlyRefEnumerable<T>
- SpanEnumerable<T>
- ReadOnlySpanEnumerable<T>
其余变动
新版本中蕴含更多内容!您能够在 GitHub release page 发布页面中查看残缺的变更日志。
您能够在 GitHub repo 找到所有的源代码,也能在 MS Learn 上找到一些手写文档,还能在 .NET API 浏览器网站中找到残缺的 API 参考文档。如果您想为新版本的改善奉献本人的力量, 请随时提问题或分割咱们,让咱们晓得您的体验!
如果您想理解无关 MVVM 工具包的更多信息,您还能够观看最近 .NET Conf 2022 中的视频。
新版本中有整套可用的 Toolkit-s 生态系统,其中有大量有用的 API 可用于构建 .NET 应用程序。祝您编码欢快!