我正在开发自己的WinForms设计器。它必须能够加载现有的自定义表单类型。我遇到的一个问题是没有默认ctor的表单:我的代码当前在将表单加载到设计器之前实例化表单,这需要默认的ctor。
OTOH,VS2008能够加载这样的表格。我相信它实际上并没有实例化我的表单(如this question中所述):即使默认ctors也没有执行。它并不真正执行InitializeComponent()。我刚刚在该函数中添加了一个消息框,但它没有显示。它看起来像动态模仿自定义表单类型,并且只执行它认为相关的InitializeComponent中的部分代码。
有谁知道我在哪里可以找到有关VS设计师如何工作的更多信息。
TIA。
注意:我发现这个related question没有满足答案
编辑:其他信息:史蒂夫指向CodeDom,这是非常有趣的。我的问题是,我需要加载到我的设计器中的类型已经编译而不是作为源代码提供。我找不到任何方法将CodeDom反序列化应用于编译代码。
答案 0 :(得分:13)
找到此here:
当您打开新的Windows时 VS中的应用项目,你看到了 在设计中称为Form1的空表单 视图。现在,你还没有建立 项目尚未实现,设计师如何? 能够创建Form1的实例 并显示出来?嗯,设计师不是 真的实例化Form1。它 正在创建基础的实例 Form1的类,即 System.Windows.Forms.Form中。有了 面向对象的基础知识 编程,你会发现这一点 直觉上有道理。当你是 设计Form1,你从开始 基类,表单,并自定义它。 这正是设计师的本质 帮助你做。
现在让我们说你添加了一堆 控制表格并关闭 设计师。当你重新打开 设计师,控制仍在 那里。但是,基类Form 没有这些控件,所以 如果设计师没有运行 Form1的构造函数,它是如何显示的 控件?设计师这样做 通过反序列化代码 的InitializeComponent。每种语言 设计师支持的有一个 CodeDomProvider负责 用于提供解析的解析器 InitializeComponent和中的代码 创建CodeDom表示 它。然后设计师调用一组 CodeDomSerializers来反序列化它 进入实际控制(或更广泛地说, 它可以添加到的组件) 设计时间表。现在,我已经掩饰了 在那里有很多细节 描述,但这里的重点是 Form1的构造函数和 InitializeComponent从来都不是 调用。相反,设计师解析 InitializeComponent中的语句 找出什么控制 实例化并添加到表单。
以上是Visual Studio中的Windows窗体设计器加载表单的方式。如果您正在寻找的是一种创建没有默认构造函数的表单实例的方法并且仍然可以访问所包含的组件/控件,我不知道有什么解决方案。我所知道的唯一方法是允许你绕过缺少默认构造函数FormatterServices.GetUninitializedObject,但要注意......
因为对象的新实例 被初始化为零,没有 构造函数运行,对象可能 不代表被视为的国家 由该对象有效。
我也有一个应用程序需要实例化已编译的表单但总是使用Activator.CreateInstance并且要求其他开发人员至少包含一个私有默认构造函数,如果他们希望在我的应用程序中访问它们的表单。由于我们拥有整个代码库,每个人都知道这个要求,这不是问题,对我们来说效果很好。
答案 1 :(得分:0)
作为对Steve的回答的补充,如果您将新的Windows窗体添加到项目中,但是将其抽象化,您仍然可以在设计器中打开它。但是,如果您添加另一个表单,并从第一个(抽象)表单派生它,则在尝试在设计器中打开表单时会出错。