Properies von unterschiedlicher Klassen die einem Objekt zur Laufzeit zugewiesen wurden bedienen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von roepke.

    Properies von unterschiedlicher Klassen die einem Objekt zur Laufzeit zugewiesen wurden bedienen

    Ich habe eine Variable vom Typ Object, der ich zur Laufzeit wahlweise unterschiedliche Klassen als Instanz aus einer liste zuordnen kann.
    Das passiert abhängig davon, welchen Eintrag der Nutzer in einer ComboBox auswählt.

    VB.NET-Quellcode

    1. Private Sub mxc_DataSource_MultiplexerControlChanged(sender As System.Object, e As System.EventArgs) Handles mxc_DataSource.MultiplexerControlChanged
    2. Me.Controls.Remove(CType(myObject, Control))
    3. myObject = lst_Filter(mxc_DataSource.piMuxSelectedIndex)
    4. Me.Controls.Add(CType(myObject, Control))
    5. End Sub

    Dieses Klassen haben Properties die ich im folgenden auch bediene.
    Im Moment mache ich das über Interfaces, da sich die Properties der Objektvariablen ja je nach zugewiesener Klasse ggf. unterscheiden können.
    Gibt es Alternativen dazu?
    Haben diese Klassen eine relevante Basisklasse oder kannst Du denen eine solche verpassen?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Finde Interfaces eigentlich ganz schick. Vererbung wäre aber auch ein Lösungsansatz. Mit Generics wäre da evtl. auch was machbar ohne das man groß Casten muss. Was ist denn der konkrete Anwendungsfall?
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Danke erst mal. Ich habe jetzt festgestellt, dass es letzlich nur um eine einzige Property geht. Eine Liste von Strings. Die übergebe ich jetzt ggf. per Interface.
    Alles Weitere lässt sich aus dieser Liste ableiten.
    Eins hab ich aber noch: aus meinen Objects habe ich UserControl gemacht, weil genau das sind sie.
    Abhängig von einer ComboBox (Eigenkreation) wird dann das entsprechende UserControl zur Laufzeit ein/ausgeblendet.
    Die zu benutzenden UserControl finden sich in einer Liste (lstFilter) und werden myUC abängig von der ComboBox zugewiesen.
    Schalte ich zwischen den UserControl mit der ComboBox hin und her klappt das aber nur genau 1x.
    Möchte ich auf ein zuvor bereits ausgewähltes UserControl zurück schalten bekomme ich eine "Auf das verworfene Objekt kann nicht zugegriffen werden." Meldung.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. '2D Liste
    2. Friend Class MultiDimList
    3. Friend ReadOnly sName As String
    4. Friend ReadOnly ucFilter As UserControl
    5. Friend Sub New(sName As String, ucFilter As UserControl)
    6. Me.sName = sName
    7. Me.ucFilter = ucFilter
    8. End Sub
    9. End Class
    10. 'Liste füllen
    11. Private Sub Init()
    12. Dim _lstItems As List(Of MultiDimList) = New List(Of MultiDimList)()
    13. _lstItems.Add(New MultiDimList("Disabled", Nothing))
    14. _lstItems.Add(New MultiDimList("Filter1", New uc_DS_Filter_2(12, 16)))
    15. _lstItems.Add(New MultiDimList("Filter2", New uc_DS_Filter_2(12, 16)))
    16. FillDataSourceMuxControlComboBoxADV(_lstItems)
    17. End Sub
    18. 'Namenseinträge aus Liste in ComboBox eintragen
    19. 'In lst_Filter werden die zugehörigen Filter UserControls kopiert.
    20. 'Ist eigentlich nicht nötig, da diese ja bereits in 'lst' zu finden sind.
    21. 'Ist hier aber noch doppelt gemoppelt.
    22. Dim lst_Filter As New List(Of UserControl)
    23. Private Sub FillDataSourceMuxControlComboBoxADV(lst As List(Of MultiDimList))
    24. mxc_DataSource.pcboMuxItems.Clear()
    25. lst_Filter.Clear()
    26. For Each _Entry In lst
    27. mxc_DataSource.pcboMuxItems.Add(_Entry.sName)
    28. lst_Filter.Add(_Entry.ucFilter)
    29. Next _Entry
    30. End Sub
    31. 'Der Anwender wählt das richtige Filter UserControl aus.
    32. Dim myUC As New UserControl
    33. Private Sub mxc_DataSource_MultiplexerControlChanged(sender As System.Object, e As System.EventArgs) Handles mxc_DataSource.MultiplexerControlChanged
    34. If Not myUC Is Nothing Then
    35. Me.Controls.Remove(CType(myUC, UserControl))
    36. CType(myUC, UserControl).Dispose()
    37. End If
    38. myUC = Nothing
    39. myUC = lst_Filter(mxc_DataSource.piMuxSelectedIndex)
    40. If Not myUC Is Nothing Then
    41. Me.Controls.Add(CType(myUC, UserControl))
    42. CType(myUC, UserControl).Visible = True 'HIER bekomme ich dann die Fehlermeldung
    43. End If
    44. End Sub

    Nun, Du disposed Dein UserControl und danach holst Du es wieder hervor. Das geht eben nicht. Eben weil es entsorgt wurde. Das hat nix mit myUC zu tun, sondern mit den Einträgen in lst. Da stecken laut Code die tw. disposed-ten UC-Instanzen drinne. Und von da holst Du sie wieder her. Was auch immer lst in Zeile#38 genau ist.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Danke, jetzt wo ich's lese, leuchtet es mir ein.
    Meine Idee war wie folgt: in Init wird eine 2d Liste gefüllt, in der jeweils eine später vom Nutzer in der ComboBox lesbare Beschreibung der Filterklasse steht die er auswählen kann und eine Instanz der zugehörigen Filterklasse selbst.
    Wird dann mittels ComboBox eine Auswahl getröffen, muss nur in der Liste der zugehörige Filter ausgewählt und im Form angezeigt werden.
    Das wollte ich machen, indem ich die Instanz des Filters aus der Liste in myUC kopiere, da ich auf die ausgewählte Filterinstanz später auch ncoh per Interfaceses zugreifen möchte.
    Das mit dem "kopieren" geht zwar, aber das disposen geht dann in die Hose weil's sich um eine Referenz handelt, d.h. ich dispose auch die Instanz in der Liste. Es ist also kein Kopieren, sondern ein Verweisen.
    Ich hab die Disposezeile jetzt weg gelassen, damit klappt's.

    Eine Frage jetzt noch, wie entsorge ich die Controls wieder sauber aus dem Speicher, sofern das Form MyForm mit den UserControls selbst geschlossen wird?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. '2D Liste
    2. Friend Class MultiDimList
    3. Friend ReadOnly sName As String
    4. Friend ReadOnly ucFilter As UserControl
    5. Friend Sub New(sName As String, ucFilter As UserControl)
    6. Me.sName = sName
    7. Me.ucFilter = ucFilter
    8. End Sub
    9. End Class
    10. 'Die Klasse des Forms beinhaltet u.A. folgendes:
    11. Friend Class MyForm
    12. 'Liste füllen
    13. Private Sub Init()
    14. Dim _lstItems As List(Of MultiDimList) = New List(Of MultiDimList)()
    15. _lstItems.Add(New MultiDimList("Disabled", Nothing))
    16. _lstItems.Add(New MultiDimList("Filter1", New UserControlInsideUserControlInsideMyForm_1(12, 16)))
    17. _lstItems.Add(New MultiDimList("Filter2", New UserControlInsideUserControlInsideMyForm_2(12, 16)))
    18. FillDataSourceMuxControlComboBoxADV(_lstItems)
    19. End Sub
    20. End Class
    21. 'Nachfolgendes wird als UserControl innerhalb von MyForm angewendet.
    22. 'U.A. kann hier dann ausgewählt werden welches weitere 'UserControlInsideUserControlInsideMyForm_x' verwendet werden soll.
    23. Friend Class UserControlInsideMyForm
    24. 'Namenseinträge aus Liste in ComboBox eintragen
    25. 'In 'lst_Filter' werden die zugehörigen Filter UserControlInsideUserControlInsideMyForm_x kopiert.
    26. Dim lst_Filter As New List(Of UserControl)
    27. Private Sub FillDataSourceMuxControlComboBoxADV(lst As List(Of MultiDimList))
    28. mxc_DataSource.pcboMuxItems.Clear()
    29. lst_Filter.Clear()
    30. For Each _Entry In lst
    31. mxc_DataSource.pcboMuxItems.Add(_Entry.sName)
    32. lst_Filter.Add(_Entry.ucFilter)
    33. Next _Entry
    34. End Sub
    35. End Class
    36. Friend Class UserControlInsideUserControlInsideMyForm_1
    37. 'Der Anwender wählt das richtige Filter UserControl aus.
    38. Dim myUC As New UserControl
    39. Private Sub mxc_DataSource_MultiplexerControlChanged(sender As System.Object, e As System.EventArgs) Handles mxc_DataSource.MultiplexerControlChanged
    40. If Not myUC Is Nothing Then
    41. Me.Controls.Remove(myUC)
    42. End If
    43. myUC = lst_Filter(mxc_DataSource.piMuxSelectedIndex)
    44. If Not myUC Is Nothing Then
    45. Me.Controls.Add(myUC)
    46. myUC.BringToFront()
    47. End If
    48. End Sub
    49. End Class


    _lstItems in Init innerhalb von MyForm müsste doch automatisch nach verlassen von Init entsorgt werden?
    lst_Filter dispose ich manuell innerhalb der Dispose() von UserControlInsideMyForm?
    myUC entsorgt sich selbst beim disposen von UserControlInsideUserControlInsideMyForm_1?

    roepke schrieb:

    _lstItems in Init innerhalb von MyForm müsste doch automatisch nach verlassen von Init entsorgt werden?
    ja

    roepke schrieb:

    lst_Filter dispose ich manuell innerhalb der Dispose() von UserControlInsideMyForm?
    Eine List(Of T) muss und kann nicht disposed werden, da sie nicht IDisposable implementiert. Oder meinst Du die UserControls darin? Ja, die solltest Du disposen, auch wenn das jetzt noch nicht in Deinem Code steht.

    roepke schrieb:

    myUC entsorgt sich selbst
    Kommt drauf an, was Du mit entsorgen meinst. Disposen: nein
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Eine List(Of T) muss und kann nicht disposed werden, da sie nicht IDisposable implementiert. Oder meinst Du die UserControls darin? Ja, die solltest Du disposen, auch wenn das jetzt noch nicht in Deinem Code steht.

    Steht nicht explizit im Beispielcode, ja. Aber genau darum geht es, die UserControls in der Liste. Ich dispose sie in der zugehörigen Dispose() des MyForm.
    Kommt drauf an, was Du mit entsorgen meinst. Disposen: nein

    myUC verweist ja nur auf einen Eintrag in lst_Filter. Deren Einträge dispose ich (s.o.), damit sollte sich myUC automatisch klären
    Wenn die lst_Filter-Einträge woanders disposed werden, muss und darf myUC nicht (nochmal) disposed werden.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.