以 Windows 形式列出(顶级)声明的变量
List (top-level) declared variables in a Windows Form
创建窗体实例后,我可以轻松地列出窗体中的所有控件。
是否有任何机制可以列出所有声明的变量或此类对象?
或许我应该称之为 declarations。只有顶级声明就足够了。
假设我们有 MyForm
表单,其中包含这样的顶级声明:
Dim Town as String
Dim ZIP as String
Dim StreetName as String
Dim StreetNo as String
Public dtCountries as DataTable
Public LstCities as List(Of String)
...
伪代码示例:
Dim MyForm as New MyForm ' create instance of the form
Dim dtVariables as New Datatable ' create a datatable to store found objects
dtVariables.Columns.Add("ID", GetTy(Int32))
dtVariables.Columns.Add("VariableName", GetTy(String))
dtVariables.Columns.Add("VariableType", GetTy(String))
For Each Varbl In MyForm.***variables*** ' <<< (how) to read all variables
Dim nr as Datarow = dtVariables.NewRow
nr("ID") = dtVariables.Rows.Count + 1
nr("VariableName") = Varbl.Name
nr("VariableType") = Varbl.GetType.ToString.Replace("System.Windows.Forms.", "")
dtVariables.Rows.Add(nr) ' add found object/variable to our datatable
Next
我要找的结果是这样的:
1 Town String
2 ZIP String
3 StreetName String
4 StreetNo Int32
5 dtCountries DataTable
6 LstCities List(Of String)
... ... ...
我知道我可以阅读 MyForm.designer.vb
文件并在那里查找声明。
这个问题是关于从 Form 的对象模型/Form 的实例中获取它的。
使用 FieldInfo objects returned by Type.GetType().GetFields()
过滤集合的示例
由于您希望此方法 return 同时 Public 和非 Public 字段,因此必须过滤集合,因为这是一个表单 class,它将包括表单包含的所有控件。
然后使用FieldType.Namespace
过滤FieldInfo
的集合,其中Namespace
不是System.Windows.Forms
.
BindingFlags设置为Instance | Public | NonPublic | DeclaredOnly
。
当 Field 表示集合(列表、字典等)时,需要解析 Type.GenericTypeArguments 属性 以提取参数集合。
我正在使用几个辅助函数来清理 字段名称并将参数集合检索为格式化字符串。
使用您发布的示例字段(我添加了一个词典来测试输出):
Dim Town As String
Dim ZIP As String
Dim StreetName As String
Dim StreetNo As String
Public dtCountries As DataTable
Public LstCities As List(Of String)
Public DictOfControls As Dictionary(Of String, Control)
这是结果:
Dim ClassFields As New DataTable
ClassFields.Columns.Add("ID", GetType(Integer))
ClassFields.Columns.Add("Name", GetType(String))
ClassFields.Columns.Add("FieldType", GetType(String))
Dim flags As BindingFlags = BindingFlags.Instance Or
BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.DeclaredOnly
Dim allFields As List(Of FieldInfo) =
Me.GetType().GetFields(flags).
Where(Function(f) (Not (f.FieldType.Namespace.Equals("System.Windows.Forms"))) AndAlso f.Name <> "components").
ToList()
For Each field As FieldInfo In allFields
Dim dr As DataRow = ClassFields.NewRow
dr("ID") = ClassFields.Rows.Count + 1
dr("Name") = field.Name
dr("FieldType") = GetFieldTypeName(field.FieldType.Name) &
GetTypeArguments(field.FieldType.GenericTypeArguments)
ClassFields.Rows.Add(dr)
Next
Private Function GetFieldTypeName(field As String) As String
Dim EndPosition As Integer = field.IndexOf(ChrW(96))
Return If(EndPosition > 0, field.Substring(0, EndPosition), field)
End Function
Private Function GetTypeArguments(args As Type()) As String
If args.Length = 0 Then Return String.Empty
Return $" ({String.Join(", ", args.Select(Function(arg) arg.Name))})"
End Function
如果Interpolated String is not available (before VB.Net version 14), use a Composite Format 字符串:
Return $" ({String.Join(", ", args.Select(Function(arg) arg.Name))})"
可以表示为:
Return String.Format(" ({0})", String.Join(", ", args.Select(Function(arg) arg.Name)))
创建窗体实例后,我可以轻松地列出窗体中的所有控件。
是否有任何机制可以列出所有声明的变量或此类对象?
或许我应该称之为 declarations。只有顶级声明就足够了。
假设我们有 MyForm
表单,其中包含这样的顶级声明:
Dim Town as String
Dim ZIP as String
Dim StreetName as String
Dim StreetNo as String
Public dtCountries as DataTable
Public LstCities as List(Of String)
...
伪代码示例:
Dim MyForm as New MyForm ' create instance of the form
Dim dtVariables as New Datatable ' create a datatable to store found objects
dtVariables.Columns.Add("ID", GetTy(Int32))
dtVariables.Columns.Add("VariableName", GetTy(String))
dtVariables.Columns.Add("VariableType", GetTy(String))
For Each Varbl In MyForm.***variables*** ' <<< (how) to read all variables
Dim nr as Datarow = dtVariables.NewRow
nr("ID") = dtVariables.Rows.Count + 1
nr("VariableName") = Varbl.Name
nr("VariableType") = Varbl.GetType.ToString.Replace("System.Windows.Forms.", "")
dtVariables.Rows.Add(nr) ' add found object/variable to our datatable
Next
我要找的结果是这样的:
1 Town String
2 ZIP String
3 StreetName String
4 StreetNo Int32
5 dtCountries DataTable
6 LstCities List(Of String)
... ... ...
我知道我可以阅读 MyForm.designer.vb
文件并在那里查找声明。
这个问题是关于从 Form 的对象模型/Form 的实例中获取它的。
使用 FieldInfo objects returned by Type.GetType().GetFields()
由于您希望此方法 return 同时 Public 和非 Public 字段,因此必须过滤集合,因为这是一个表单 class,它将包括表单包含的所有控件。
然后使用FieldType.Namespace
过滤FieldInfo
的集合,其中Namespace
不是System.Windows.Forms
.
BindingFlags设置为Instance | Public | NonPublic | DeclaredOnly
。
当 Field 表示集合(列表、字典等)时,需要解析 Type.GenericTypeArguments 属性 以提取参数集合。
我正在使用几个辅助函数来清理 字段名称并将参数集合检索为格式化字符串。
使用您发布的示例字段(我添加了一个词典来测试输出):
Dim Town As String
Dim ZIP As String
Dim StreetName As String
Dim StreetNo As String
Public dtCountries As DataTable
Public LstCities As List(Of String)
Public DictOfControls As Dictionary(Of String, Control)
这是结果:
Dim ClassFields As New DataTable
ClassFields.Columns.Add("ID", GetType(Integer))
ClassFields.Columns.Add("Name", GetType(String))
ClassFields.Columns.Add("FieldType", GetType(String))
Dim flags As BindingFlags = BindingFlags.Instance Or
BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.DeclaredOnly
Dim allFields As List(Of FieldInfo) =
Me.GetType().GetFields(flags).
Where(Function(f) (Not (f.FieldType.Namespace.Equals("System.Windows.Forms"))) AndAlso f.Name <> "components").
ToList()
For Each field As FieldInfo In allFields
Dim dr As DataRow = ClassFields.NewRow
dr("ID") = ClassFields.Rows.Count + 1
dr("Name") = field.Name
dr("FieldType") = GetFieldTypeName(field.FieldType.Name) &
GetTypeArguments(field.FieldType.GenericTypeArguments)
ClassFields.Rows.Add(dr)
Next
Private Function GetFieldTypeName(field As String) As String
Dim EndPosition As Integer = field.IndexOf(ChrW(96))
Return If(EndPosition > 0, field.Substring(0, EndPosition), field)
End Function
Private Function GetTypeArguments(args As Type()) As String
If args.Length = 0 Then Return String.Empty
Return $" ({String.Join(", ", args.Select(Function(arg) arg.Name))})"
End Function
如果Interpolated String is not available (before VB.Net version 14), use a Composite Format 字符串:
Return $" ({String.Join(", ", args.Select(Function(arg) arg.Name))})"
可以表示为:
Return String.Format(" ({0})", String.Join(", ", args.Select(Function(arg) arg.Name)))