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

Oak*_*548 3 .net vb.net reflection system.reflection winforms

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

是否有任何机制可以列出所有声明的变量或此类对象?
也许我应该称之为声明。仅顶层声明就足够了。

假设我们有带有MyForm这样顶级声明的 Form:

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)
...
Run Code Online (Sandbox Code Playgroud)

伪代码示例:

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
Run Code Online (Sandbox Code Playgroud)

我正在寻找的结果是这样的:

 1   Town         String
 2   ZIP          String
 3   StreetName   String
 4   StreetNo     Int32
 5   dtCountries  DataTable
 6   LstCities    List(Of String)
 ... ...          ...
Run Code Online (Sandbox Code Playgroud)

我知道我可以读取MyForm.designer.vb文件并在那里查找声明。
这个问题是关于从表单/表单实例的对象模型中获取它。

Jim*_*imi 5

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

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

BindingFlags设置为Instance | Public | NonPublic | DeclaredOnly

当 Field 表示 Collection(列表、字典等)时,需要解析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)
Run Code Online (Sandbox Code Playgroud)

这是结果:

类 GetType 获取字段

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
Run Code Online (Sandbox Code Playgroud)

如果插值字符串不可用(VB.Net 版本 14 之前),请使用复合格式字符串:

Return $" ({String.Join(", ", args.Select(Function(arg) arg.Name))})"
Run Code Online (Sandbox Code Playgroud)

可以表示为:

Return String.Format(" ({0})", String.Join(", ", args.Select(Function(arg) arg.Name)))
Run Code Online (Sandbox Code Playgroud)