建设网站需要哪些素材,网站图片翻页怎么做,哪个网站可以用MC皮肤做图片,江苏公司响应式网站建设报价点击上方蓝字关注我们#xff08;本文阅读时间#xff1a;10分钟)我们很高兴地宣布正式推出新的 .NET 社区工具包#xff0c;现在已经在NuGet上发布了8.0.0版本#xff01;这是一个重要版本#xff0c;包括大量新功能、改进、优化、错误修复#xff0c;许多反映了全新项目…点击上方蓝字关注我们本文阅读时间10分钟)我们很高兴地宣布正式推出新的 .NET 社区工具包现在已经在NuGet上发布了8.0.0版本这是一个重要版本包括大量新功能、改进、优化、错误修复许多反映了全新项目结构和组织的重构这篇文章将详细描述这些内容。与每个社区工具包版本一样所有的更改都受到使用该工具包的微软团队和社区其他开发人员反馈的影响。我们非常感谢所有做出贡献并不断帮助 .NET 社区工具包变得更好的人.NET 社区工具包中有什么.NET 社区工具包是一组适用于所有 .NET 开发人员的帮助程序和 API独立于任何特定的 UI 平台。该工具包由 Microsoft 维护和发布是 .NET 基金会的一部分。它也被一些内部项目和收件箱应用程序使用例如 Microsoft Store。从新的 8.0.0 版本开始该项目现在位于 GitHub 上的 CommunityToolkit/dotnet 存储库中其中包括作为 Toolkit 一部分的所有库。所有可用的 API 都不依赖于任何特定的运行时或框架因此所有 .NET 开发人员都可以使用它们。这些库是从 .NET Standard 2.0 到 .NET 6 的多目标库所以它们既可以支持尽可能多的平台又可以在与较新的运行时一起使用时进行优化以获得最佳性能。.NET 社区工具包中的库包括CommunityToolkit.CommonCommunityToolkit.Mvvm又名“微软 MVVM 工具包”CommunityToolkit.DiagnosticsCommunityToolkit.HighPerformanceCommunityToolkit/dotnet:https://github.com/CommunityToolkit/dotnet社区工具包历史一览 您可能想知道为什么 .NET 社区工具包的第一个版本是 8.0.0 版本。好问题原因是 .NET 社区工具包的所有库最初都是Windows 社区工具包的一部分它是帮助程序、扩展和自定义控件的集合和自定义控件可简化和演示为 Windows 10 和 Windows 11 构建 UWP 和 .NET 应用程序的常见开发人员任务。随着时间的推移仅针对 .NET 且没有任何 Windows 特定依赖项的 API 数量不断增加我们决定将它们拆分到一个单独的项目中以便它们可以独立发展并且对于不进行任何 Windows 开发的 .NET 开发人员来说也更容易找到。.NET 社区工具包就是这样诞生的。这也使我们更容易且更好地组织文档现在每个特定于平台的工具包都有其单独的文档。由于分支之前的 Windows 社区工具包的最后一个版本是 7.1.x我们决定遵循该语义版本号以使现有用户更容易理解转换这就是 .NET 社区工具包的第一个版本是 8.0.0 的原因。 展望未来它将与 Windows 社区工具包分开进行版本控制因为每个项目都有自己独立的路线图和发布时间表。搞清楚这些之后现在让我们深入了解 .NET 社区工具包库的这个新的主要版本中的所有新功能Windows 社区工具包https://github.com/CommunityToolkit/WindowsCommunityToolkit文档https://docs.microsoft.com/zh-cn/dotnet/communitytoolkit/?ocidAID3052907MVVM 工具包正如之前在7.0 版本中宣布的那样.NET 社区工具包的主要组件之一是 MVVM 工具包一个现代的、快速的、平台无关和模块化的 MVVM 库。这与 Microsoft Store、照片应用程序等使用的 MVVM 库相同MVVM 工具包受到MvvmLight的启发并且由于该库已被弃用MVVM工具包也就是MvvmLight的官方替代品。我们在开发 MVVM 工具包的同时也与Laurent Bugnion合作他支持 MVVM 工具包作为现有 MvvmLight 用户的升级道路我们也有这方面的迁移文档。MVVM工具包是基于以下几个关键原则构建的:平台无关意味着它不依赖于特定的 UI 框架。您可以使用它在 UWP、WinUI 3、MAUI、WPF、Avalonia、Uno 等之间共享代码运行时无关该库支持多目标并支持低至 .NET Standard 2.0的环境这意味着您可以在现代运行时例如 .NET 6上运行时获得性能改进并且即使在 .NET 框架上仍然可以使用它。易于上手和使用对使用的应用程序结构或编码模式没有严格的要求。您可以使用该库来适应您自己的架构和风格。À la carte所有组件都是独立的也可以单独使用。没有强迫您使用“全部”的方法如果您只想使用整个库中的一种类型您可以做得很好然后根据需要逐渐开始使用更多功能。参考实现所有可用的 API 都是精简和高性能的为 .NET 基类库中包含的接口提供“参考实现”但缺乏直接使用它们的具体类型。例如您将能够找到 INotifyPropertyChanged 或 ICommand 等接口的“参考实现”。7.0 版本:https://blogs.windows.com/windowsdeveloper/2021/03/16/announcing-windows-community-toolkit-v7-0/MvvmLight:https://www.nuget.org/packages/MvvmLightLaurent Bugnion:https://twitter.com/LBugnion迁移文档:https://docs.microsoft.com/zh-cn/dotnet/communitytoolkit/mvvm/migratingfrommvvmlight?ocidAID3052907MVVM 工具包源生成器MVVM Toolkit 8.0.0 版本中最大的新特性是新的 MVVM 源代码生成器它旨在大大减少使用 MVVM 设置应用程序所需的样板代码。与我们在 7.1.0 中发布的预览生成器相比它们也被完全重写为增量生成器这意味着它们的运行速度将比以前更快并且即使在处理大型项目时也会有助于保持 IDE 的快速响应。您可以在此处找到有关新源生成器的所有文档如果您更喜欢视频版本James Montemagno 还制作了几个关于它们的视频。让我们也回顾一下由源生成器提供支持的主要功能您可以在 MVVM 工具包中找到这些功能。MVVM 源代码生成器https://docs.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/overview?ocidAID3052907在 7.1.0 中发布的预览生成器https://devblogs.microsoft.com/ifdef-windows/windows-community-toolkit-7-1-preview-release/?ocidAID3052907增量生成器https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md视频https://www.youtube.com/watch?vAXpTeiWtbC8t600s命令创建命令可能是非常重复的在为每个方法设置一个属性的需求下我们希望以抽象的方式向应用程序中用于调用它们的各种UI组件(如按钮)公开这些方法。这就是新的 [RelayCommand] 属性发挥作用的地方这将使 MVVM 工具包自动生成具有正确签名的命令使用库中包含的 RelayCommand 类型具体取决于带注释的方法。作为比较以下是从前人们通常会如何设置命令的代码private IRelayCommandUser greetUserCommand;public IRelayCommandUser GreetUserCommand greetUserCommand ?? new RelayCommandUser(GreetUser);private void GreetUser(User user)
{Console.WriteLine($Hello {user.Name}!);
}现在可以简化为[RelayCommand]
private void GreetUser(User user)
{Console.WriteLine($Hello {user.Name}!);
}源生成器将负责根据带注释的方法创建正确的 GreetUserCommand 属性。此外您可以指定 CanExecute 方法还可以控制异步命令的并发级别。还有其他选项可以微调生成的命令的行为您可以在我们的文档中了解更多信息。在我们的文档中https://docs.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/?ocidAID3052907可观察的属性编写可观察属性可能非常冗长尤其是当您还必须添加额外的逻辑来处理被通知的依赖属性时。现在通过使用 MVVM 工具包中的新属性并让源生成器在幕后创建可观察的属性所有这些都可以大大简化。这些新属性是 [ObservableProperty]、[NotifyPropertyChangedFor] 和 [NotifyCanExecuteChangedFor]、[NotifyDataErrorInfo] 和 [NotifyPropertyChangedRecipients]。接下来让我们快速回顾一下所有这些新属性可以做什么。考虑一个场景其中有两个可观察属性一个依赖属性和上面定义的命令当两个可观察属性中的任何一个发生变化时都需要通知依赖属性和命令。也就是说每当 FirstName 或 LastName 更改时也会通知 FullName 以及 GreetUserCommand。这就是过去的做法private string? firstName;public string? FirstName
{get firstName;set{if (SetProperty(ref firstName, value)){OnPropertyChanged(nameof(FullName));GreetUserCommand.NotifyCanExecuteChanged();}}
}private string? lastName;public string? LastName
{get lastName;set{if (SetProperty(ref lastName, value)){OnPropertyChanged(nameof(FullName));GreetUserCommand.NotifyCanExecuteChanged();}}
}public string? FullName ${FirstName} {LastName};现在可以全部改写如下[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
[NotifyCanExecuteChangedFor(nameof(GreetUserCommand))]
private string? firstName;[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
[NotifyCanExecuteChangedFor(nameof(GreetUserCommand))]
private string? lastName;public string? FullName ${FirstName} {LastName};MVVM 工具包将处理这些属性的代码生成包括插入所有逻辑以引发指定的属性更改或执行更改事件。但是等等还有更多的特性当使用 [ObservableProperty] 生成可观察属性时MVVM 工具包 现在还将生成两个没有实现的部分方法OnPROPERTY_NAMEChanging 和 OnPROPERTY_NAMEChanged 。这些方法可用于在更改属性时注入额外的逻辑而无需回退到使用手动属性。请注意由于这两个方法是部分的、返回 void 且没有定义如果未实现它们C# 编译器将完全删除它们这意味着它们在不使用时会消失并且不会添加到应用程序中间。这是如何使用它们的示例[ObservableProperty]
private string name;partial void OnNameChanging(string name)
{Console.WriteLine($The name is about to change to {name}!);
}partial void OnNameChanged(string name)
{Console.WriteLine($The name just changed to {name}!);
}当然您也可以只使用这两种方法中的一种或者不使用任何一种。从上面的代码片段中源生成器将生成类似于以下的代码public string Name
{get name;set{if (!EqualityComparerstring.Default.Equals(name, value)){OnNameChanging(value);OnPropertyChanging();name value;OnNameChanged();OnPropertyChanged();}}
}partial void OnNameChanging(string name);partial void OnNameChanged(string name);[ObservableProperty] 属性还支持验证如果表示属性的任何字段具有一个或多个继承自 ValidationAttribute 的属性这些属性将自动复制到生成的属性中因此在使用 ObservableValidator 创建可验证的属性时也完全支持这种方法。如果您还希望在设置其值时验证该属性您还可以添加 [NotifyDataErrorInfo] 以在属性设置器中生成验证代码。[ObservableProperty]还有更多可用的功能就像命令一样您可以关于它们的信息并在我们的文档中查看更多示例。在我们的文档中https://docs.microsoft.com/zh-cn/dotnet/communitytoolkit/mvvm/generators/overview?ocidAID3052907取消对命令的支持[RelayCommand] 属性中添加了一个新属性可用于指示源生成器在原始命令旁边生成取消命令。此取消命令可用于取消异步命令的执行。这也展示了 [RelayCommand] 如何自动适应异步方法和接受参数的方法并在后台创建异步命令的实现。这还启用了其他功能例如易于设置绑定以显示进度指示器等等。这是如何使用它们的示例[RelayCommand(IncludeCancelCommand true)]
private async Task DoWorkAsync(CancellationToken token)
{// 使用取消支持做一些长期运行的工作
}从这个小片段中生成器将生成以下代码private AsyncRelayCommand? doWorkCommand;public IAsyncRelayCommand DoWorkCommand doWorkCommand ?? new AsyncRelayCommand(DoWorkAsync);ICommand? doWorkCancelCommand;public ICommand DoWorkCancelCommand doWorkCancelCommand ?? IAsyncRelayCommandExtensions.CreateCancelCommand(UpdateSomethingCommand);生成的代码与 IAsyncRelayCommandExtensions.CreateCancelCommand API 中的逻辑相结合让您只需一行代码即可生成命令在工作开始或运行时通知 UI并具有自动并发控制命令是 当它已经运行时命令是默认禁用的。每当主命令开始或结束运行时将通知单独的取消命令并在执行时向传递给主命令包装的方法的令牌发出取消信号。所有这些完全抽象出来只需一个属性即可轻松访问。对生成属性的 Broadcast 的更改支持我们还添加了一个新的 [NotifyPropertyChangedRecipients] 属性该属性可用于从继承自 ObservableRecipient或使用 [ObservableRecipient] 注释的类型生成的可观察属性。使用它将生成对 Broadcast 方法的调用以向所有其他订阅组件发送有关刚刚发生的属性更改的消息。这在视图模型的属性更改还需要通知应用程序中的其他组件的情况下很有用假设有一个 IsLoggedIn 布尔属性当用户登录时更新这可以通知并触发应用程序来刷新 Broadcast 消息。它可以按如下方式使用[ObservableProperty]
[NotifyPropertyChangedRecipients]
private string name;这将产生与此类似的代码public string Name
{get name;set{if (!EqualityComparerstring.Default.Equals(name, value)){OnNameChanging(value);OnPropertyChanging();string oldValue name;name value;Broadcast(oldValue, value, nameof(Name));OnNameChanged();OnPropertyChanged();}}
}这是另一个增强生成的属性并确保它们可以在几乎所有场景中使用而不会被迫回退到手动属性的功能。ViewModel 组成C# 没有多重继承这有时会成为障碍。如果有一个必须从特定类型继承的视图模型但您还想向其中注入 INotifyPropertyChanged 支持或者让它也从 ObservableRecipient 继承以访问其 API该怎么办MVVM 工具包现在通过引入代码生成属性来解决这个问题这些属性允许将这些类型的逻辑注入到任意类中。它们是 [INotifyPropertyChanged]、[ObservableObject] 和 [ObservableRecipient]。将它们添加到一个类将导致 MVVM 工具包源代码生成器将该类型的所有逻辑包含到该类中就好像该类也继承自该类型一样。例如[INotifyPropertyChanged]
partial class MyObservableViewModel : DatabaseItem
{
}此 MyObservableViewModel 将像您所期望的那样继承自 DatabaseItem但使用 [INotifyPropertyChanged] 将使其也支持 INotifyPropertyChanged以及 ObservableObject 自身包含的所有帮助 API。我们仍然建议在需要时从基本类型例如 ObservableObject继承因为这也有助于减少二进制大小但是在需要的时候以这种方式注入代码的能力可以帮助在无法改变视图模型的基本类型的情况下解决c#的限制就像上面的例子一样。改进的 Messenger API MVVM 工具包 中另一个常用的特性是 IMessenger 接口它是一种类型合约可用于在不同对象之间交换消息。这对于解耦应用程序的不同模块而不必保持对引用类型的强引用很有用。还可以将消息发送到特定通道由令牌唯一标识并在应用程序的不同部分具有不同的信使。MVVM 工具包 提供了这个接口的两种实现WeakReferenceMessenger它不会固定收件人并允许收集他们。这是通过依赖句柄实现的这是一种特殊类型的 GC 引用它允许此信使确保始终允许收集已注册的接收者即使已注册的处理程序将它们引用回来但不存在对它们的其他未完成的强引用。StrongReferenceMessenger这是一个信使实现它对已注册的接收者进行根权限化以确保它们保持活跃状态即使信使是唯一引用它们的对象。下面是一个如何使用这个接口的小例子// 声明消息
public sealed record LoggedInUserChangedMessage(User user);
// 明确注册收件人...
messenger.RegisterMyViewModel, LoggedInUserChangedMessage(this, static (r, m)
{
// 在这里处理消息r 是接收者m 是接收者
// 输入消息。使用作为输入传递的接收者使得
// ambda 表达式不捕获“this”从而提高性能。
});// ... 或者让视图模型实现 IRecipientTMessage......
class MyViewModel : IRecipientLoggedInUserChangedMessage
{public void Receive(LoggedInUserChangedMessage message){// 在这里处理消息}
}// ... 然后通过接口注册其他API也可用messenger.RegisterLoggedInuserChangedMessage(this);// 从其他模块发送消息
messenger.Send(new LoggedInUserChangedMessage(user));由于新提供的公共 DependentHandle API这个新版本的 MVVM 工具包中的信使实现在 .NET 6 中得到了高度优化它允许信使类型变得比以前更快并提供完全零分配的消息广播。以下是一些基准展示了 MVVM 工具包中的信使与其他广泛使用的 MVVM 库中的其他几种等效类型的比较方法中位数错误标准差比率比率标准差第0代第一代已分配MVVMToolkitStrong4.025 ms0.0177 ms0.0147 ms10–––MVVMToolkitWeak7.549 ms0.0815 ms0.0762 ms1.870.02–––MvvmCrossStrong11.483 ms0.0226 ms0.0177 ms2.850.019687.5–41,824,022 BMvvmCrossWeak13.941 ms0.1865 ms0.1744 ms3.470.049687.5–41,824,007 BMVVMLight52.929 ms0.1295 ms0.1011 ms13.140.067600–33,120,010 BStylet91.540 ms0.6362 ms0.4967 ms22.730.1735500–153,152,352 BMvvmGen141.743 ms2.7249 ms2.7983 ms35.310.719250–83,328,348 BCatel148.867 ms2.6825 ms2.5093 ms36.940.645250–22,736,316 BPrism150.077 ms0.5359 ms0.4184 ms37.260.131750025076,096,900 BCaliburnMicro280.740 ms3.7625 ms3.1418 ms69.740.82880002000381,859,608 BMauiMessagingCenter673.656 ms1.7619 ms1.3755 ms167.260.638000–35,588,776 B每个基准测试运行涉及向 100 个收件人发送 4 条不同的消息 1000 次。如您所见WeakReferenceMessenger 和 StrongReferenceMessenger 都是迄今为止最快的也是唯一一个在广播消息时甚至不分配一个字节的 。公共 DependentHandle API:https://github.com/dotnet/runtime/pull/54246改进的集合 API这个新版本的 MVVM 工具包 还将所有可观察的分组集合类型从 CommunityToolkit.Common 包移动到 CommunityToolkit.Mvvm同时还进行了一些重大更改以改进 API 表面并使其在更多场景中有用。这些 API 在处理分组项目时特别有用例如显示联系人列表它们现在还包括扩展以极大地促进常见操作例如在组内的正确位置插入项目使用默认比较器 或输入一个并在需要时创建一个新组。这个视频展示了来自 MVVM Toolkit 示例应用程序的简单联系人视图宣布 MVVM 工具包示例应用程序为了配合新版本我们还在 Microsoft Store 中发布了示例应用程序它包括 MS Docs 上可以找到的所有文档以及许多可用 API 的交互式示例。它旨在成为 MVVM 工具包的伴侣我们希望它能帮助人们开始使用这个库从而更加熟悉它从 Microsoft Store 下载并试用Microsoft Store:https://apps.microsoft.com/store/detail/9NKLCF1LVZ5H?hlzh-cnglCN改进的诊断 APICommunityToolkit.Diagnostics 包也获得了一些新的改进利用了新的 C# 10 内插字符串处理程序和调用者参数表达式功能。一些以前接受字符串的 Guard API 现在也接受自定义处理程序允许调用站点在没有抛出异常的情况下完全跳过插值步骤而且也不再需要手动指示参数名称。这是一个快速的前后比较// 诊断 7.1
public static void SampleMethod(int[] array, int index, Spanint span, string text)
{Guard.IsNotNull(array, nameof(array));Guard.HasSizeGreaterThanOrEqualTo(array, 10, nameof(array));Guard.IsInRangeFor(index, array, nameof(index));Guard.HasSizeLessThanOrEqualTo(array, span, nameof(span));Guard.IsNotNullOrEmpty(text, nameof(text));
}// 诊断 8.0
public static void SampleMethod(int[] array, int index, Spanint span, string text)
{Guard.IsNotNull(array);Guard.HasSizeGreaterThanOrEqualTo(array, 10);Guard.IsInRangeFor(index, array);Guard.HasSizeLessThanOrEqualTo(array, span);Guard.IsNotNullOrEmpty(text);
}C# 10 内插字符串处理程序https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/tutorials/interpolated-string-handler?ocidAID3052907调用者参数表达式https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression?ocidAID3052907.NET 6 支持这个新版本的 .NET 社区工具包还增加了对 .NET 6 的支持将其作为所有可用库的新目标。在最新的 .NET 运行时上运行时带来了一些改进现在为所有库启用了修剪支持。为了支持这一点所有包还为所有 API 提供了完整的修整注释以确保所有内容要么对链接器友好要么在编译时显式显示正确的警告例如MVVM 工具包中的某些验证 API 就是这种情况 它们使用 BCL 中的一些 API这些 API 本质上需要一些反射才能工作。High Performance 包中的 CountT() 扩展现在也支持 mint 和 nunit。为 .NET 6 上的所有包引入了其他几项优化。当然所有库都将继续支持 .NET Standard 2.0因此您也可以继续从具有不同目标框架的项目中引用它们。由于 NuGet 包解析的工作原理如果您使用这些包和较低目标框架例如 .NET Standard 2.0编写库并且消费者从针对较新 .NET 版本的项目中引用它例如.NET 6)他们仍然会自动获得可用的 .NET 社区工具包 程序集的最优化版本在这个新版本中还有更多内容您可以在 GitHub 发布页面上查看完整的变更日志。您可以在我们的 GitHub 存储库中找到所有源代码在MS Docs 网站上找到一些手写文档在 .NET API 浏览器网站上找到完整的 API 参考。如果您想做出贡献请随时提出问题或联系我们让我们了解您的体验要关注 Twitter 上的对话请使用 #CommunityToolkit 标签。您的所有反馈都极大地帮助了这些库的发展方向因此请务必分享它们GitHub 存储库https://github.com/CommunityToolkit/dotnetMS Docs 网站https://docs.microsoft.com/en-us/dotnet/communitytoolkit/?ocidAID3052907谢谢你读完了本文欢迎在评论区留言分享你的想法并且转发到朋友圈。长按识别二维码关注微软开发者MSDN点击「阅读原文」了解.NET社区工具包~