ModelStudio






3.20/5 (4投票s)
类图和代码生成工具。
引言
在您实际开始编程软件之前,类图在为软件系统开发模型方面非常重要。它们为设计人员、架构师和开发人员提供了一个图形界面,用于操作方法、属性、字段、事件,以及像类、接口、结构等数据结构。在本文中,我们将使用我称之为 ModelStudio 的设计器来帮助您在直接深入代码之前创建模型结构,并且在我们与这个设计器交互时,应注意代码将在后台更新,之后使用 System.CodeDom
命名空间进行自动生成。
背景
我认为首先对代码进行建模是面向对象编程和设计优秀软件应用程序架构的一个良好开端。如果您正在寻找一种反射式解决方案,那么您可能想看看 Sacha Barber 的 100% 反射式类图创建工具。对于本文不讨论的图表工具,我修改并使用了 Barber 工具中的 ClassDrawerContainerPanel
和相关类。我还想承认 Chagosoft 的 cDOMx 类生成器 中的一些想法。
使用 ModelStudio
ModelStudio 应用程序使用 ModelStudio 框架(我们称之为)来创建 Visual Basic 和 C# 代码文档。使用 ModelStudio 非常直接。
- 当您启动程序时,您会看到一个空白画布。
- 要开始创建您的第一个类,只需单击“新建命名空间”按钮,为其命名,然后就会创建一个新的
Namespace
对象。 - 然后,只需从左侧选择命名空间即可添加“新建导入”或“新建类”。
- 要向类添加属性和方法,只需选择所需的类并使用“新建属性”或“新建方法”按钮。向方法添加参数也非常简单;只需从左侧选择方法并单击“新建参数”。
- 当您对项目满意时,您可以通过以下选项来获取代码:
- 使用“生成代码”按钮以您想要的语言检索项目的代码。
- 使用“生成文件”按钮以您想要的语言在选定文件夹中生成单独的类文档。
- 您还可以选择将项目(存储库)另存为文件,以便将来进行编辑或传输,方法是单击“保存”按钮。
- 要打开项目文件,请使用“打开”按钮,浏览到该文件,项目将被加载。
目的
关于我创建此资源工具的初衷,我需要添加一点说明。从 Visual Studio 2005 开始,Microsoft 包含了一个他们称之为 类设计器 的工具。类设计器工具可能适合您的组织,特别是如果您拥有功能强大的 Visual Studio Team System。但是,我不喜欢类设计器工具的“小缺点”。例如,我希望所有生成的类在类构造时初始化任何自定义类型。
Books = New List(of Book)
类设计器却忽略了这一点。其次,难道不希望所有属性都有完整的 setter 和 getter,并且自动声明关联的字段吗?类设计器也忽略了这一点。相反,类设计器默认只提供一个原型化的类属性。
原型
Public Overridable Property Name() As String
Get
End Get
Set(ByVal value As String)
End Set
End Property
理想
Private m_Name As String
Public Overridable Property Name() As String
Get
Return Me.m_Name
End Get
Set(ByVal value As String)
Me.m_Name = value
End Set
End Property
框架
ModelStudio 框架实现了一个简单的设计,它首先将类信息封装到一个简单的类“外观”中。这里我们 liberal 地使用了“外观”一词。定义:“事物的表面外观或假象。(例如:他们设法维持了财富的外观)”。这些外观类及其中的数据随后被“翻译”(我们将在后面讨论),以创建用于代码生成的实际 CodeDom 类。
外观
CodeDomImport
描述:这是一个示例外观类,将用于为生成的类创建新的 Imports
(即 using
)语句。
Public Class CodeDomImport
Implements ICodeMember
Private m_Import As String = "System.Text"
Private m_Parent As Object
''' Initialize a new instance of the CodeDomImport object
''' The fully qualified Namespace that will be imported ie: System.Text
Sub New(ByVal ImportName As String)
m_Import = ImportName
End Sub
''' The fully qualified Namespace that represents the import ie: System.text
Public Property Name() As String Implements ICodeMember.Name
Get
Return m_Import
End Get
Set(ByVal value As String)
m_Import = value
End Set
End Property
Public Property Parent() As Object
Get
Return m_Parent
End Get
Set(ByVal value As Object)
m_Parent= value
End Set
End Property
End Class
CodeGenerator 类
这是整个项目的核心部分。这里是将实际代码翻译、准备并生成到代码文件的位置。
基本上,这个类的结构不是理想的。但是,为了本文的目的,所有内容都包含在这个类中。翻译发生在我们返回一个常规的 CodeDOM CodeNamespace
时。
转换
Public Function GetNamespace(ByVal _Namespace As CodeDomNamespace) As CodeNamespace
Dim _space As CodeDomNamespace = _Namespace
Dim _ns As CodeNamespace = _Namespace.DOMNameSpace
'==Imports
If _space.Imports.Count > 0 Then
For Each import As CodeDomImport In _space.Imports
Dim im As New CodeNamespaceImport(import.Name)
_ns.Imports.Add(im)
Next
End If
....
End Function
准备工作
现在,我们需要按照我们想要的方式准备代码以供输出。在我们称之为准备阶段,您将使用以下 CodeDom 命名空间:
Imports System.CodeDom
Imports System.CodeDom.Compiler
为了准备类在类构造时初始化所有自定义类型,我们使用以下代码:
Dim mcdClass As CodeTypeDeclaration = _Class.DOMClass
'Constructors
For Each meth As CodeDomMethod In _Class.Constructors
If meth.Parameters.Count > 0 Or _Class.CustomTypes.Count > 0 Then
Dim cnstr As New CodeDom.CodeConstructor
For Each param As CodeDomParameter In meth.Parameters
cnstr.Parameters.Add(New _
CodeParameterDeclarationExpression(param.Type, param.Name))
Next
' Here is where custom initialization begins
For Each p As CodeDomProperty In _Class.CustomTypes
Dim this As New CodeThisReferenceExpression()
Dim leftExpression As New CodePropertyReferenceExpression(this, p.Name)
Dim rightExpression As New _
CodeObjectCreateExpression(New CodeTypeReference(p.Type))
Dim assign As New CodeAssignStatement(leftExpression, rightExpression)
cnstr.Statements.Add(assign)
Next p
mcdClass.Members.Add(cnstr)
End If
Next meth
现在,您可以通过简单地调整上述命令以满足您自己的个人偏好来更改构造函数,以初始化您想要的任何类型。
生成
这就是我们实际输出已翻译和准备好的内容的地方。显然,我们将在这里生成 VB 代码,但也有一个类似的 C# 生成方法。
Private Sub GenerateVBFile(ByVal n As CodeNamespace, ByVal OutputDirectory As String)
m_Unit = New CodeCompileUnit
m_Unit.Namespaces.Add(n)
' Generate the code with the VB code provider.
Dim provider As Microsoft.VisualBasic.VBCodeProvider = _
New Microsoft.VisualBasic.VBCodeProvider
' Build the output file name.
For Each c As CodeDom.CodeTypeDeclaration In n.Types
Dim tempUnit As New CodeCompileUnit
tempUnit.Namespaces.Add(New CodeDom.CodeNamespace(n.Name))
tempUnit.Namespaces(0).Types.Add(c)
' Build the output file name.
Dim sourceFile As String = OutputDirectory + _
Path.DirectorySeparatorChar + c.Name + "." + provider.FileExtension
' Create a TextWriter to a StreamWriter to an output file.
Using tw As New IndentedTextWriter(New StreamWriter(sourceFile, False), " ")
' Generate source code using the code provider.
provider.GenerateCodeFromCompileUnit(tempUnit, tw, New CodeGeneratorOptions())
' Close the output file.
tw.Close()
End Using
Next c
End Sub
非常简单,只需设置私有成员并调用 VBCodeProvider
的 GenerateCodeFromCompileUnit
即可输出一个类,该类应如下所示:
Namespace Classroom
Public Class Student
Private m_Name As String
Private m_StudentID As Integer
Private m_MyTeacher As Teacher
Private m_MyChair As Chair
Private m_IsSpecial As Boolean
Private m_Books As List(Of Book)
Private Sub New()
MyBase.New
Me.MyTeacher = New Teacher
Me.MyChair = New Chair
Me.Books = New List(Of Book)
End Sub
Public Overridable Property Name() As [String]
Get
Return Me.m_Name
End Get
Set
Me.m_Name = value
End Set
End Property
...
End Class
End Namespace
总结
最后一步是我们将所有生成的类导入到我们的项目解决方案中。构建并运行它。恭喜,现在真正的工作开始了。