List (top-level) declared variables in a Windows F

2019-07-08 02:10发布

I can easily list all controls in a Form, after creating an instance of it.

Is there any mechanism to list all declared variables or such objects?
Perhaps I shall call it declarations. Only top-level declarations are enough.

Let's assume we have MyForm Form with such top-level declarations:

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)
...

Pseudo-code example:

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

The result I am looking for is something like:

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

I know that I can read MyForm.designer.vb file and look there for declarations.
This question is about getting it from an object model of a Form / instance of a Form.

1条回答
SAY GOODBYE
2楼-- · 2019-07-08 02:59

An example using a filtered collection of FieldInfo objects returned by Type.GetType().GetFields()

Since you want this method to return both Public and non-Public Fields, the collection must be filtered because, since this is a Form class, it will include all the controls a Form contains.
The collection of FieldInfo is then filtered using FieldType.Namespace, where the Namespace is not System.Windows.Forms.

The BindingFlags are set to Instance | Public | NonPublic | DeclaredOnly.

When the Field represents a Collection (List, Dictionary etc.), the Type.GenericTypeArguments property needs to be parsed to extract the arguments Collection.

I'm using a couple of helper functions to clean up the Fields Name and to retrieve the collection of arguments as a formatted string.

Using the sample Fields you posted (I added a Dictionary to test the output):

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)

this is the result:

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

If Interpolated String is not available (before VB.Net version 14), use a Composite Format string:

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

can be expressed as:

Return String.Format(" ({0})", String.Join(", ", args.Select(Function(arg) arg.Name)))
查看更多
登录 后发表回答