在Windows窗体中列出(顶级)声明的变量

时间:2018-12-29 11:28:53

标签: vb.net winforms variables reflection system.reflection

创建窗体的实例后,我可以轻松列出窗体中的所有控件。

有没有列出所有 声明的变量 或此类对象的机制?
也许我将其称为声明。仅顶级声明就足够了。

假设我们有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的实例中获取它的。

1 个答案:

答案 0 :(得分:4)

使用FieldInfo返回的Type.GetType().GetFields()个对象的过滤集合的示例

由于您希望此方法返回公共字段和非公共字段,因此必须对集合进行过滤,因为由于这是一个Form类,它将包含一个Form包含的所有控件。
然后使用FieldInfo过滤FieldType.Namespace的集合,其中 Namespace 不是 System.Windows.Forms

BindingFlags设置为Instance | Public | NonPublic | DeclaredOnly

当字段表示集合(列表,字典等)时,需要解析Type.GenericTypeArguments属性以提取参数Collection。

我正在使用几个辅助函数来清理字段名称,并以格式化字符串的形式检索参数集合。

使用您发布的示例字段(我添加了字典来测试输出):

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)

这是结果:

Class GetType GetFields

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不可用(VB.Net版本14之前),请使用Composite Format字符串:

Return $" ({String.Join(", ", args.Select(Function(arg) arg.Name))})"

可以表示为:

Return String.Format(" ({0})", String.Join(", ", args.Select(Function(arg) arg.Name)))