Jasonwc Ответов: 3

Установите переменную с циклом, используя имя переменной в виде строки


Всем Привет. Мое приложение требует, чтобы переменные устанавливались и извлекались несколько раз в разных формах и подменах. Вместо того чтобы писать код несколько раз, я надеялся использовать цикл для циклического перебора переменных и установки их соответствующим образом. Это то, что у меня есть до сих пор. Я застрял с установкой переменной на основе ее имени (см. ниже).
Dim VariableA As Integer
Dim VariableB As String
Dim VariableC As Boolean
Dim VariableD As Double
Dim VariableNames(3) As String
Dim VariableValues(3) As String

Private Sub SetVariables()

    VariableNames = {"VariableA", "VariableB", "VariableC", "VariableD"}
    VariableValues = {"1", "Hello", "True", "2.234"}

    For i As Integer = 0 To VariableNames.Length - 1
        SetValue(VariableNames(i), VariableValues(i))
    Next

End Sub

Private Sub SetValue(ByVal Name As String, ByVal value As Object)

    'what do i add here

End Sub


Что я уже пробовал:

Я пробовал словарь, но он только ссылается на значение, а не устанавливает переменную

3 Ответов

Рейтинг:
2

Jasonwc

Спасибо, Дэйв. Я займусь методом литья

Я подумал, что упрощенный пример будет более полезным. вот мой точный код.

В разделе imedialty ниже представлены классы меню. Этот бит работает как и ожидалось

Public Class MenuItem

    Public Name As String
    Public Type As TypeEnum

    Enum TypeEnum
        CheckBox
        ComboBox
        TextBox
    End Enum     

    Public Sub New()
    End Sub

End Class

Public Class Menu

    Public MenuItems() As MenuItem
    Public Name As String
    Public LinkedVariable as Object

    Public Sub New()
    End Sub

    Public Sub AddMenuItem(ByVal ItemName As String, _
                           ByVal ItemType As MenuItem.TypeEnum, _
                           ByVal ItemLinkedVariable as Object)   

        If MenuItems Is Nothing Then
            ReDim MenuItems(0)
        Else
            ReDim Preserve MenuItems(MenuItems.Length)
        End If
        MenuItems(MenuItems.Length - 1) = New MenuItem
        MenuItems(MenuItems.Length - 1).Name = ItemName
        MenuItems(MenuItems.Length - 1).Type = ItemType
        MenuItems(MenuItems.Length - 1).LinkedVariable = ItemLinkedVariable 
    End Sub

End Class


Постройте меню в основном классе форм. Этот бит работает как и ожидалось

Public Class Form1
    Public Settings As New SettingsForm
    Public Sub CreateMenu()

        Settings.AddMenu("Menu1")

        Settings.Menus(0).AddMenuItem("CheckBoxA", MenuItem.TypeEnum.CheckBox, VariableA)
        Settings.Menus(0).AddMenuItem("TextBoxB", MenuItem.TypeEnum.TextBox, VariableB)
        Settings.Menus(0).AddMenuItem("TextBoxC", MenuItem.TypeEnum.TextBox, VariableC) 

        Settings.AddMenu("Menu2")

        Settings.Menus(1).AddMenuItem("CheckBoxD", MenuItem.TypeEnum.CheckBox, VariableD)
        Settings.Menus(1).AddMenuItem("TextBoxE", MenuItem.TypeEnum.TextBox, VariableE)

        'etc......      

        Settings.Build()

        Settings.Show()

    End Sub
End Class


Public Class SettingsForm
    Public Menus() As Menu

    Public VariableA As Boolean
    Public VariableB As String
    Public VariableC As String
    Public VariableD As Boolean
    Public VariableE As String

    Public Sub New()

        InitializeComponent()

    End Sub

    Public Sub Build()

        SettingsTabControl.TabPages.Clear()

        If Menus IsNot Nothing Then
            For i As Integer = 0 To Menus.Length - 1

                SettingsTabControl.TabPages.Add(Menus(i).Name)
                SettingsTabControl.TabPages(i).Name = Menus(i).Name & "TabPage"
                SettingsTabControl.TabPages(i).Text = Menus(i).Name

                AddSettingsItems(Menus(i), i)

            Next
        End If

    End Sub

    Public Sub AddSettingsItems(ByVal SelectedMenu As Menu, ByVal TabPageIndex As Integer)
        Dim y As Integer = 50
        Dim yinc As Integer = 25

        If SelectedMenu IsNot Nothing Then
            If SelectedMenu.MenuItems IsNot Nothing Then

                For i As Integer = 0 To SelectedMenu.MenuItems.Length - 1

                    Dim formObj As Object

                    'Specific Settings
                    Select Case SelectedMenu.MenuItems(i).Type
                        Case MenuItem.TypeEnum.CheckBox
                            formObj = New CheckBox
                        Case MenuItem.TypeEnum.ComboBox
                            formObj = New ComboBox                            
                        Case MenuItem.TypeEnum.TextBox
                            formObj = New TextBox
                            formObj.TextAlign = HorizontalAlignment.Right
                            formObj.BorderStyle = BorderStyle.FixedSingle
                    End Select

                    formObj.Name = SelectedMenu.MenuItems(i).Name
                    formObj.Location = New Point(25, y)
                    SettingsTabControl.TabPages(TabPageIndex).Controls.Add(formObj)

                    y = y + yinc
                Next
            End If
        End If
    End Sub
End Class


Это тот бит,на котором я застрял,я хочу иметь возможность устанавливать переменные A,B,C, D, E из элементов управления, которые были добавлены в SettingsTabControl. Однако я не могу понять, как связать переменные с объектами LinkedVariable в каждом меню. Это то что у меня есть но это не работает

Private Sub SettingsFromOkButton_Click(sender As Object, e As EventArgs) Handles OkButton.Click

    For m As Integer = 0 To Menus.Length - 1
        For i As Integer = 0 To Menus(m).MenuItems.Length

            Dim currentcontrol As Object = SettingsTabControl.TabPages(m).Controls(Menus(m).MenuItems(i).Name)

            Select Case Menus(m).MenuItems(i).Type
                Case MenuItem.TypeEnum.CheckBox
                    If currentcontrol.CheckedState = True Then
                        Menus(m).MenuItems(i).LinkedVariable = True
                    Else
                        Menus(m).MenuItems(i).LinkedVariable = False
                    End If
                Case MenuItem.TypeEnum.ComboBox


                Case MenuItem.TypeEnum.TextBox
                    Menus(m).MenuItems(i).LinkedVariable = currentcontrol.Text
            End Select

        Next
    Next

    MsgBox(VariableA & vbCrLf _
           VariableB & vbCrLf _
           VariableC & vbCrLf _
           VariableD & vbCrLf _
           VariableE & vbCrLf)

End Sub


Рейтинг:
0

Dave Kreskowiak

Да, ты не можешь этого сделать.

На самом деле в файле .NET нет такой вещи, как "глобальная" переменная. Самое близкое, что вы получите, - это статический (Общий в VB.NET) класс или модуль. Я бы рекомендовал идти по маршруту статического класса.

Проблема с этим заключается в том, что это выглядит так, как будто вы пытаетесь реализовать "мешок собственности". Это набор пар ключ/значение, где ключ всегда является строкой, а значение может быть любого типа. В основном, это:

Dim _bag As Dictionary(Of String, Object)

Есть несколько проблем с этим. Одна довольно неприятная вещь заключается в том, что вы теряете безопасность типа. Вы можете установить "переменную", на самом деле просто ключ в словаре, для любого типа значения, которое вы хотите. Итак, если переменная должна быть целым числом, но вы случайно пишете в нее строку, ничто не скажет, что вы сделали что-то не так, пока код, считывающий "целое число", не взорвется и не вызовет исключение.

Затем есть приведение значений к тому, что ожидается, бокс/распаковка ...

Было бы лучше, если бы у вас был фиксированный набор переменных, и если вам действительно нужно, чтобы они были "глобальными", предоставьте их как общие свойства в общем классе. Вы сохраняете безопасность типов, производительность и более легко поддерживаемый (читай: отлаживаемый) код.

Но если вы вообще используете "глобальные" переменные, это намек на то, что вам, вероятно, придется переосмыслить то, как вы разрабатываете свой код.


Рейтинг:
0

Jasonwc

Я использовал отражение

Dim Flags As BindingFlags = BindingFlags.GetField Or BindingFlags.Instance Or BindingFlags.Public
Dim fVar As System.Reflection.FieldInfo = Me.GetType.GetField(ObjectName, Flags)

If TypeOf SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName) Is TextBox Then
    ctrlValue = SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName).Text
ElseIf TypeOf SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName) Is CheckBox Then
    ctrlValue = CType(SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName), CheckBox).Checked
ElseIf TypeOf SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName) Is RadioButton Then
    ctrlValue = CType(SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName), RadioButton).Checked
End If

fVar.SetValue(Me, ctrlValue)