Beantwortet Abrufen von Html-Daten in Klasse kapseln

  • Samstag, 28. April 2012 10:51
     
      Enthält Code

    Hallo,

    ich möchte das Abrufen einiger HTML-Daten in eine Klasse kapseln. Meine Frage ist, ob es besser ist, das Abrufen der Daten in den Konstruktor zu packen (VARIANTE 1) oder lieber eine Public Methode definieren und diese verwenden (VARIANTE 2)? Die Klasse mit den zwei Möglichkeiten habe ich unten aufgelistet:

    Public Class Class1
    
        Private m_Eigenschaft1 As String
        Public ReadOnly Property Eigenschaft1() As String
            Get
                Return m_Eigenschaft1
            End Get
        End Property
    
        Private m_Eigenschaft2 As String
        Public ReadOnly Property Eigenschaft2() As String
            Get
                Return m_Eigenschaft2
            End Get
        End Property
    
        ' Hier befinden sich weitere Eigenschaften
    
        Private m_Url As String
        Public Property Url() As String
            Get
                Return m_Url
            End Get
            Set(ByVal value As String)
                m_Url = value
            End Set
        End Property
    
        ' **************
        ' * VARIANTE 1 *
        ' **************
        Public Sub New(ByVal url As String)
            m_Url = url
            GetUrlData()
        End Sub
    
        Private Sub GetUrlData()
            If IsNothing(m_Url) Then
                Throw New ArgumentNullException("Url sollte nicht Null sein.")
            ElseIf m_Url.Length = 0 Then
                Throw New ArgumentException("Url sollte nicht leer sein.")
            End If
            ' Hier Daten aus Url ermitteln und Eigenschaften setzen
        End Sub
    
        ' **************
        ' * VARIANTE 2 *
        ' **************
        Public Sub New(ByVal url As String)
            m_Url = url
        End Sub
    
        Public Sub GetUrlData()
            If IsNothing(m_Url) Then
                Throw New ArgumentNullException("Url sollte nicht Null sein.")
            ElseIf m_Url.Length = 0 Then
                Throw New ArgumentException("Url sollte nicht leer sein.")
            End If
            ' Hier Daten aus Url ermitteln und Eigenschaften setzen
        End Sub
    
    End Class

    Gibt es vielleicht eine bessere Alternative?

    Gruss,

    LittleBlueBird

Alle Antworten

  • Samstag, 28. April 2012 19:33
    Beantworter
     
     Beantwortet

    Hallo,

    schau Dir System.Uri an, dort findest Du bereits eine vollständige Klasse, die u. a. HTTP abdeckt
    (und deren teilweise diffizilen Besonderheiten). In den meisten Fällen fährt damit besser,
    als mit einer eigenen Lösung, da sie von anderen .NET Methoden (z. B. WebClient) ebenfalls verwendet wird.

    Zum allgemeinen Teil, ob Eigenschaft oder Konstruktor:
    Grundsätzlich kannst Du ab VB 2010 auch Eigenschaften mit gemischtem Zugriff erstellen, siehe
    Gewusst wie: Deklarieren einer Eigenschaft mit gemischten Zugriffsebenen (Visual Basic)

    Damit kann Parameter im Konstruktor (Sub New) über die Eigenschaftszuweisung erstellen
    somit man eine zusätzliche Methoden vermeiden kann - hier:
    Verlagere die Tests aus GetUrlData in den Setter von Url.

    Was die Ausnahmen angeht, so ist es immer etwas problematisch, wenn sie im Konstruktor auftreten,
    da Du damit keine gültige Instanz hast.

    Gruß Elmar

  • Sonntag, 29. April 2012 08:50
     
      Enthält Code

    Hallo Elmar,

    besten Dank für Deine Antwort. Ich benutze bereits die HtmlAgilityPack Library, um die Html-Daten zu laden und zu parsen. System.Uri war nicht so leistungsfähig. Ausserdem verwende ich noch die Newtonsoft.Json Library, um die Javascript-Daten zu verarbeiten. Das alles passiert in der Methode GetUrlData.

    Wenn ich Deine Erklärung richtig interpretiert habe, dann müsste ich in etwa folgende Klasse haben:

    Public Class Class1
    
        Private m_Eigenschaft1 As String
        Public ReadOnly Property Eigenschaft1() As String
            Get
                Return m_Eigenschaft1
            End Get
        End Property
    
        Private m_Eigenschaft2 As String
        Public ReadOnly Property Eigenschaft2() As String
            Get
                Return m_Eigenschaft2
            End Get
        End Property
    
        ' Hier befinden sich weitere Eigenschaften
    
        Private m_Url As String
        Public Property Url() As String
            Get
                Return m_Url
            End Get
            Private Set(ByVal value As String)
                If IsNothing(value) Then
                    Throw New ArgumentNullException("Url sollte nicht Null sein.")
                ElseIf value.Length = 0 Then
                    Throw New ArgumentException("Url sollte nicht leer sein.")
                Else
                    m_Url = value
                End If
            End Set
        End Property
    
        Public Sub New(ByVal url As String)
            Me.Url = url
        End Sub
    
        Public Sub GetUrlData()
            ' Hier Daten aus Url ermitteln und Eigenschaften setzen
        End Sub
    
    End Class

    In diesem Fall kann ich keinen parameterlosen Konstruktor mehr verwenden. Demzufolge kann ich die Url nicht mehr über die Eigenschaft sondern lediglich über den parametrierten Konstruktor setzen. Meines Erachtens ist es besser, wenn ich den Setter auch als Public definiere. Ich kann ihn immer noch im Konstruktor verwenden und gleichzeitig direkt setzen, so wie unten aufgeführt:

    Public Class Class1
    
        Private m_Eigenschaft1 As String
        Public ReadOnly Property Eigenschaft1() As String
            Get
                Return m_Eigenschaft1
            End Get
        End Property
    
        Private m_Eigenschaft2 As String
        Public ReadOnly Property Eigenschaft2() As String
            Get
                Return m_Eigenschaft2
            End Get
        End Property
    
        ' Hier befinden sich weitere Eigenschaften
    
        Private m_Url As String
        Public Property Url() As String
            Get
                Return m_Url
            End Get
            Set(ByVal value As String)
                If IsNothing(value) Then
                    Throw New ArgumentNullException("Url sollte nicht Null sein.")
                ElseIf value.Length = 0 Then
                    Throw New ArgumentException("Url sollte nicht leer sein.")
                Else
                    m_Url = value
                End If
            End Set
        End Property
    
        Public Sub New()
        End Sub
    
        Public Sub New(ByVal url As String)
            Me.Url = url ' Hier weise ich den Wert der Eigenschaft zu statt der Membervariablen
        End Sub
    
        Public Sub GetUrlData()
            ' Hier Daten aus Url ermitteln und Eigenschaften setzen
        End Sub
    
    End Class

    Die Ausnahmen betreffend gebe ich Dir vollkommen Recht. Wobei ich schon Klassen gesehen habe, die im Konstruktor eine Ausnahme auslösen. Ich habe mir das abgeschaut und bei mir dann verwendet in der Annahme, es sei korrekt.

    Gruss LittleBlueBird

    EDIT: Jetzt habe ich kapiert, was Du mit "zusätzliche Methode vermeiden" meintest. Ich soll nicht nur die Tests auf Null und Leerstring in den Setter verlagern, sondern auch die Datenermittlung und das Setzen der Eingeschaft1,2,...

    • Bearbeitet LittleBlueBird Montag, 30. April 2012 08:58 Ergänzung
    •