Verständnisfrage: Shared und wie kann ich ein Klassenobjekt allen Klassen zugänglich machen?

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Verständnisfrage: Shared und wie kann ich ein Klassenobjekt allen Klassen zugänglich machen?

    Hallo,

    ich möchte Fehlerausgabe vereinheitlichen und habe dafür eine Klasse, in der aus einer Ini-Datei die Fehlermeldungen nach Sprachen und Fehlerbezeichnungen sortiert eingelesen werden (in eine Ini-Klasse, sie ist schon vorhanden). Somit muss ich aus anderen Klassen nur die Sprache (sie ist global) und Fehlerbezeichnung übergeben und die Meldung wird in dieser Sprache ausgegeben.

    Nur, wie mache ich es, dass alle Klassen auf das gleiche Objekt ("ErrMsg") zugreifen? Ich habe als Erstes an "Shared" gedacht, aber man kann keine "Shared Class" machen.

    Soll ich ein "Shared ErrMsg As New ErrorMessage" in einer Form erstellen? Aber wie greifen dann die anderen Formen darauf zu?

    Danke schön.

    LG

    sonne75 schrieb:

    aber man kann keine "Shared Class" machen.
    Du kannst aber eine Public Class mit nur Shared Procedures bestücken.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nochmal zu meinem Verständnis: ich habe ein Private Member Ini und 2 Subs, eine zum Laden der Ini und eine andere zur Ausgabe der Fehlermeldung.
    Laden erfolgt ja nur einmal beim Starten des Programms. Aber die Ausgabe will ich von den verschiedenen Formen aus aufrufen.

    Wenn die Ausgabe shared ist, greifen dann alle Aufrufe auf das gleiche Objekt (dieses Private Ini)? Muss ich dafür trotzdem in jeder Form ein eigenes ErrMsg-Objekt instanzieren?
    Entweder du erstellt in jeder Form eine Instanz deiner Klasse und hast somit Zugriff auf diese Sub.
    Oder du erstellt dir eine Klasse mit Shared Members (wie bereits gesagt).

    Sieh dir mal als Vergleich die Klasse System.IO.File und System.IO.FileInfo an.
    Die Klasse .File hat ausschließlich Shared Member. Man muss aber zu jeder Methode einen Filenamen mit angeben damit er weiß welche Datei es zu behandelt gilt.
    Die Klasse .FileInfo hingegen muss mit dem Dateinamen im Konstruktor initialisiert werden (somit weiß dieses Objekt um welche Datei es sich handelt). Die Methoden benötigen in diesem Fall den Dateinamen nicht mehr.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    In deinem Fall würde sich eventuell eine Singleton Klasse anbieten.
    Bsp.:

    VB.NET-Quellcode

    1. Public Class DeineKlasse
    2. Private Sub New() ' WICHTIG Private
    3. End Sub
    4. Private Shared einzigartigeKlasse As DeineKlasse = New DeineKlasse()
    5. Public Shared Function getInstance() As DeineKlasse
    6. Return einzigartigeKlasse
    7. End Function
    8. Public test As Integer = 10
    9. Public Sub machwas()
    10. test += 10
    11. End Sub
    12. End Class


    Somit gibt es nur mehr eine einzige Instanz deiner Klasse.

    Um darauf zugreifen zu können lässt du dir das Objekt der Singleton-Klasse ausgeben (geht in egal welcher Form)

    VB.NET-Quellcode

    1. Dim c As DeineKlasse = DeineKlasse.getInstance
    2. c.machwas()
    3. Debug.Print(c.test.ToString)


    Manche leute halten jedoch nicht viel Singleton Klassen, da es etwas gegen das OOP Prinzip "verstoßt"
    Such sonst dazu im Netz nach Vor- und Nachteilen von Singleton-Mustern.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten

    sonne75 schrieb:

    Vorteil zu einem Modul?
    Es ist .NET.
    Ein Modul ist in VB.NET nur gut, eine Befehlserweiterung zu schreiben, sonst gibt es keine Verwendung dafür.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Und Singleton-Klassen sind da besser? Irgendwie sieht es für mich zu kompliziert aus, es müsste doch auch einfacher gehen, wenn man eine Funktionalität aus verschiedenen Klassen abrufen will (da wäre es ja blöd, wenn jede dieser Klassen ein eigenes ErrorMessage-Objekt mit eingelesenen Daten erstellt, wenn es sowieso alles enthält).

    sonne75 schrieb:

    wenn jede dieser Klassen ein eigenes ErrorMessage-Objekt mit eingelesenen Daten erstellt
    DAfür gibt es doch abgeleitete Klassen.
    Mach Dir eine Basisklasse mit einer entsprechenden Shared Funktionalität, die wäre dann nur in einer Instanz da.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wie meinst du das? Bei mir gibt es in der Klasse ja ein Ini-Objekt (als Dictionary intern), wenn ich eine Klasse ableite, wird Funktionalität vererbt, aber das Objekt wird doch neu erzeugt oder? Oder wo soll ich Shared davor schreiben?

    VB.NET-Quellcode

    1. Public Class ErrorMsg
    2. Private ErrorIni As New ConfigIni
    3. Public Sub Load(ByVal path As String)
    4. ErrorIni.LoadFile(path)
    5. End Sub
    6. Public Sub ShowErrMsg(ByVal LngID As Integer, ByVal Err As String)
    7. MessageBox.Show(ErrorIni.GetValue(LngID.ToString, Err, ""))
    8. End Sub
    9. End Class


    Ich habe mir gerade überlegt, wenn ich "Private Shared ErrorIni As ConfigIni" schreibe und dann einfach in jeder Form, wo ich es brauche ein Objekt instanziere: dann müssten alle Objekte und Objekt.ShowErrMsg(1031, "InitError") auf die gleiche ErrorIni zugreifen? Und laden brauche ich auch nur einmal am Anfang, mit einem der Objekte (Objekt.Load(path))?

    Wobei ich mir gerade noch überlegt habe, dass ich keine Sprache übermittle, sondern My.Application.UICulture.Name abfrage und das meine Sectionnamen dann sind...

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „sonne75“ ()

    Am einfachsten wäre es wenn du dir in dieser Klasse einen Konstruktor bastelst welcher den Ini-Pfad übergeben muss.
    Innerhalb dieses Konstruktors machst du dann gleich dieses LoadFile.

    In jeder Form wo du das dann benötigst erstellst du eine Instanz dieser Klasse.
    Den Pfad zur Ini wirst du ja irgendwo gespeichert haben denk ich.

    Shared und "nicht" Shared sollte man nicht mischen wenn diese miteinander kommunizieren, da dies oft komisches Verhalten an den Tag legen kann.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Ich habe es ausprobiert, es hat funktioniert.

    Ich habe "Private Shared ErrorIni as ConfigIni". Dann rufe ich bei der MainForm-Load-Funktion einfach die Load-Sub vom dortigen Objekt ErrMsg. Und in einer anderen Form habe ich auch ein Objekt ErrMsg (auch als New instanziert) und da rufe ich nur ShowErrMsg auf.

    Main:

    VB.NET-Quellcode

    1. Public ErrMessage As New ErrorMsg
    2. Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    3. ErrorMessage.Load("LS/error.txt")
    4. .....
    5. End Sub


    frmID:

    VB.NET-Quellcode

    1. Public ErrMsg As New ErrorMsg
    2. Sub .....
    3. If.....
    4. ErrMsg.ShowErrMsg("IDRange")


    Spricht etwas dagegen? Es passiert genau das, was ich will: einmal irgendwo geladen und alle Formen greifen auf das gleiche Objekt.

    EDIT: wenn ich im Konstruktor gleich lade und mehrmals das Objekt instanziere, dann würde ich mehrmals laden, das will ich doch nicht. Es reicht, wenn einmal geladen wird.
    Hier ist mit guten Gründen beabsichtigt, den Objektorientierten Stil zu verlassen, nämlich um Anwendungsweit dasselbe Objekt bereitzustellen, es also mit allen zu teilen (Shared).
    Und da isses schnurzpieps, ob das Ziel mit einem Modul erreicht wird oder mit einem Singleton, oder mit Shared Properties in ieiner Klasse.

    Nur deine letzte Lösung ist paradox. Weil da wird in jedem Form ein eigenes ErrorMsg - Dingens instanziert, aber in Wirklichkeit willst du garnicht für jedes Form etwas eigenes, sondern alle sollen sich dasselbe teilen.

    Du willst halt ein globales Message-Teil für alle, und deshalb darf das Schlüsselwort New nicht auftauchen, denn New erzeugt immer eine lokale Instanz von irgendwas.

    ErfinderDesRades schrieb:

    Hier ist mit guten Gründen beabsichtigt, den Objektorientierten Stil zu verlassen, nämlich um Anwendungsweit dasselbe Objekt bereitzustellen, es also mit allen zu teilen (Shared).
    Und da isses schnurzpieps, ob das Ziel mit einem Modul erreicht wird oder mit einem Singleton, oder mit Shared Properties in ieiner Klasse.


    Ja, so habe ich es mir auch gedacht, aber hier wird ein Modul fast "verabscheut".

    Wie soll ich es dann machen? Wenn ich kein New schreibe, dann ist es doch eine leere Zuweisung und er kann darauf nicht zugreifen oder?

    Wie kann ich es in meiner Lösungsvariante schreiben?

    Ansonsten kann ich daraus natürlich auch ein Module machen.
    Ja, es ist ähnlich, wie ich mich gefragt habe, warum man statt einer Property (in der man nur Get und Set nach Standard macht) nicht einfach Public Variable nimmt, im Endeffekt ist es doch völlig das Gleiche - man hat unbeschränkten Zugriff über den Namen.
    Ich habe hierfür gesucht und die obige Erklärung auch gefunden.

    Aber wie soll ich denn das "New" in meinem Fall vermeiden? Oder einfach Modul verwenden?