乐趣区

关于winform:更新-WinForms-InitializeComponent-的现代代码生成

当你应用 Visual Studio 中的 WinForms Designer 来创立一个 WinForms 表单或用户控件时,它并没有像 XML 或 HTML 那样的非凡定义或文件格式来示意用户界面。从一开始,WinForms 应用的惟一格局就是程序代码。在 WinForms Visual Basic 我的项目中定义的表单或用户控件会被保留到 VB 代码中。在 C# 我的项目中,这就是 C# 代码。这些代码将被搁置在一个专用的 Designer 文件中,该文件位于理论表单代码文件前面,也蕴含管制 UI 的代码。

当你的表单或用户控件须要在 WinForms Designer 中再次关上时,该代码将被解释并依据后果对象图在 Designer 中从新创立表单 / 用户控件。这就是咱们把保留表单的过程称为 CodeDOM 序列化的起因。这里的 CodeDOM 指的是一种对象模型(Code Document object model,代码文档对象模型),它容许开发人员通过特定类型的对象来定义程序的各个方面或程序的一部分。

尽管 CodeDOM 很灵便,能够比拟容易地进行扩大,并且反对比 Visual Basic 或 C# 更多的语言,然而从现有的代码文件生成 CodeDOM 图是一件齐全不同的事件。尽管 CodeDOM 能够通过现有的编译器实现为特定的语言编写代码文件,但生成的代码格调依然是 .NET 框架刚开始时的格调,在许多状况下曾经不再合乎以后的编码标准。

在 WinForms 中,当你设计一个表单的时候,所有相干的内容都是在每个表单或用户控件的一个办法中生成的。这个办法 (还有一些根底构造和初始化代码) 叫做 InitializeComponent。

这个办法会被表单的构造函数无条件地调用。在 C# 中,这是非常明显的,你增加到我的项目中的新表单总是具备构造函数和所需的调用:

public partial class Form1 : Form
    {public Form2()
        {InitializeComponent();
        }
    }

在 Visual Basic 中,如果你不显式地增加构造函数 Sub New,Visual Basic 编译器会在后盾主动插入对 InitializeComponent 的调用。但如果你在代码文件中增加了一个构造函数,编辑器也会在 VB 代码中插入对 InitializeComponent 的调用:

Public Class Form1

    Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

    End SubEnd Class

留神,在 Visual Basic 中,Inherits 语句容许新表单类继承 System.Windows.Forms.Form 基类,与 C# 不同的是,它只是 Designer 代码暗藏文件的一部分。在 VB 中,分部类只需在其中一个分部类的代码文件中申明 partial 关键字即可。这就是为什么 Visual Basic WinForms 表单代码文件默认不蕴含任何货色,只蕴含表单的类定义的起因。

直到最近,WinForms Designer 应用 CodeModel 接口来解释不同编码语言的源代码,以构建所需的外部 CodeDOM 图,以便 Designer 保留表单或用户控件的定义。然而咱们扭转了这一点。

Enter Roslyn

WinForms 在 Visual Studio 2022 17.5 版本中引入了一种现代化的形式,来读取和生成 WinForms 过程外 Designer 的 InitializeComponent 代码。它通过 应用 .NET 编译器平台的 API(通常称为 Roslyn SDK)来实现所有相干工作。Roslyn 编译器是一套针对 .NET 语言的开源编译器和代码剖析 API。它容许开发人员应用古代语言个性在 C# 和 Visual basic .NET 中编写、剖析和操作代码。它还提供了一套丰盛的诊断和代码重构性能,以进步代码品质和开发人员的工作效率。它是 C# 和 VB 代码生成的黄金规范和以后的最佳实际。而且,因为它与 Visual Studio 中用于编译和构建任何 C# 或 Visual Basic 我的项目的工具雷同,因而其代码生成后果完全符合以后的编码标准。

此外,因为 Roslyn 编译器提供了某些  API,不仅晓得特定语句、命令或办法的正确语法,而且还晓得在 WinForms 设计时代码块的语义,WinForms Designer 能够比以前更早、更准确地指出 InitializeComponent 外部代码潜在的问题。因而,它不仅晓得你什么时候拼错了“Buttne”——它还晓得在 InitializeComponent 外部定义的拼写错误的变量将是一个未知的符号,并且可能指出这一点。

然而还有一系列额定的益处:

  • 以前,基于 CodeModel 构建 CodeDOM 只能在 UI Thread 上运行。这不仅是一种阻塞操作,而且无奈充分发挥古代多核处理器的后劲。应用 Roslyn 编译器,咱们将能够通过应用并行化来优化构建的过程。
  • 旧的零碎没有一种简略的办法来解释最近引入的语言个性。而应用 Roslyn,咱们能够抉择引入像 NameOf 这样的语言个性来生成更优的代码,特地是用于数据绑定的时候。此外,它为将来 InitializeComponent 外部更简单的代码生成开拓了新的路线,这将有助于优化和平衡在具备不同 HighDPI 设置的机器上的 HighDPI 场景的代码生成。
  • Roslyn 编译器反对许多方面的 .editorconfig 配置,因而在 InitializeComponent 中生成的代码靠近于您和您的团队通过自定义 .editorconfig 定义强制执行的编码标准。

总而言之,有一些编码元素与之前的有实质上的不同。C# 中 this 或 Visual Basic 中 Me 的省略就是一个例子。上面的截图显示了 Roslyn 在 InitializeComponent 中 Button 的代码生成的区别:

如果你对将 WinForms Designer 中的代码生成转移到 Roslyn 或如何应用 .editorconfig 配置 InitializeComponent 代码生成的更多技术背景感兴趣,请查看 WinForms 库中的这篇技术文章,它更具体地解释了所有这些内容。

对于这个主题的反馈对咱们来说真的很重要,请在文章下方留言通知咱们你在 WinForms 代码生成方面的想法或意见。如果你对 WinForms Designer 有任何倡议,或者发现了一个 bug,请随时在 WinForms Github 库中提交新的 issue。编码欢快!

退出移动版