none
Typübernahme von Me in der Basisklasse RRS feed

  • Frage

  • Hallo,
    ich habe einen Serialisier zum 1:1 Kopieren beliebiger Objekte. In der Basisklasse möchte ich eine Funktion implementieren, die mir definiert Eigenschaften der Kopie ändert. Wie muss die Syntax bei "As Object" jeweils lauten, damit ich dort den gleichen Typ wie "Me" bekomme? Me.GetType gibt es nicht.

        Public Function GetKopieSpezial() As Object
            Dim merke As Object = Serialiser.GetKopie(Me)
            With DirectCast(merke, IBasis)
                .Guid = System.Guid.NewGuid.ToString("N").ToLower
                .Name = .PraefixName + .Guid
                .GuidVorlage = DirectCast(Me, IBasis).Guid
            End With
            Return merke
        End Function


    Peter

    Mittwoch, 4. Juli 2012 21:41

Antworten

  • Hallo Peter,

    das könnte so funktionieren.

    Module Module1
      Public Sub Main()
        Dim objA As New KlasseA
        Dim objB As New KlasseB

        ' objA.GetKopie hat einen Rückgabewert vom Typ KlasseA.
        Dim objA1 = objA.GetKopie

        ' objB.GetKopie hat einen Rückgabewert vom Typ KlasseB.
        Dim objB1 = objB.GetKopie
      End Sub


      <Serializable()> Public MustInherit Class BasisKlasse
        Public Guid As String
        Public GuidVorlage As String
      End Class


      <Serializable()> Public MustInherit Class BasisKlasse_Derived(Of clsDerivedClass_TP As BasisKlasse)
        Inherits BasisKlasse

        Public Function GetKopie() As clsDerivedClass_TP
          Dim kopie As BasisKlasse = GetDuplikat(Me)
          kopie.GuidVorlage = Me.Guid
          Return DirectCast(kopie, clsDerivedClass_TP)
        End Function
      End Class


      <Serializable()> Public Class KlasseA
        Inherits BasisKlasse_Derived(Of KlasseA)
      End Class

      <Serializable()> Public Class KlasseB
        Inherits BasisKlasse_Derived(Of KlasseB)
      End Class


      Public Function GetDuplikat(Of T)(ByVal obj As T) As T
        Dim memoStream = New System.IO.MemoryStream
        Dim binFormatter = New Runtime.Serialization.Formatters.Binary.BinaryFormatter
        binFormatter.Serialize(memoStream, obj)
        memoStream.Position = 0
        Return CType(binFormatter.Deserialize(memoStream), T)
      End Function
    End Module



    Donnerstag, 5. Juli 2012 19:56

Alle Antworten

  • Hallo Peter,

    wenn ich Dich richtig verstanden habe ( was ich einfach mal bezweifle ;-) ) sollte As Object einfach As NameDeinerKlasse sein.

    z.B.

    Public Class Test
        Public Function GetKopieSpezial() as Test
            Dim merke As Test
            ....
            Return merke
        End Function
    End Class
      '


    Hannes

    If you have got questions about this, just ask.

    In a perfect world,
    users would never enter data in the wrong form,
    files they choose to open would always exist
    and code would never have bugs.

    C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/

    Donnerstag, 5. Juli 2012 05:57
  • ich der Tat war mein Anliegen nicht richtig verstanden. Mit nachfolgendem Code funktioniert das ganze, aber ich hätte gerne den GetKopie-Return irgendwie generisch im selben Typ wie die zu kopierende Klasse.

        Public Sub Main()
            Dim objA As New KlasseA
            Dim objB As New KlasseB
            Dim objA2 = objA.GetKopie
            Dim objB2 = objB.GetKopie
        End Sub
    
    
        <Serializable()> Public MustInherit Class BasisKlasse
            Public Guid As String
            Public GuidVorlage As String
            Public Function GetKopie() As Object
                Dim kopie = GetDuplikat(Me)
                kopie.GuidVorlage = Me.Guid
                Return kopie
            End Function
        End Class
    
        <Serializable()> Public Class KlasseA
            Inherits BasisKlasse
        End Class
    
        <Serializable()> Public Class KlasseB
            Inherits BasisKlasse
        End Class
    
        Public Shared Function GetDuplikat(Of T)(ByVal obj As T) As T
            Dim memoStream = New System.IO.MemoryStream
            Dim binFormatter = New Runtime.Serialization.Formatters.Binary.BinaryFormatter
            binFormatter.Serialize(memoStream, obj)
            memoStream.Position = 0
            Return CType(binFormatter.Deserialize(memoStream), T)
        End Function

    mit folgenden überladenen Methoden ginge es auch, aber generisch in einer Funktion ist halt eleganter

    ...
           Dim objA2 As KlasseA = BasisKlasse.GetKopie(objA)
    ...
    
            Public Shared Function GetKopie(ByVal obj As KlasseA) As KlasseA
                Dim kopie = GetDuplikat(obj)
                kopie.GuidVorlage = obj.Guid
                Return kopie
            End Function
            Public Shared Function GetKopie(ByVal obj As KlasseB) As KlasseB
                Dim kopie = GetDuplikat(obj)
                kopie.GuidVorlage = obj.Guid
                Return kopie
            End Function
    


    Peter

    Donnerstag, 5. Juli 2012 17:42
  • Hallo Peter,

    das könnte so funktionieren.

    Module Module1
      Public Sub Main()
        Dim objA As New KlasseA
        Dim objB As New KlasseB

        ' objA.GetKopie hat einen Rückgabewert vom Typ KlasseA.
        Dim objA1 = objA.GetKopie

        ' objB.GetKopie hat einen Rückgabewert vom Typ KlasseB.
        Dim objB1 = objB.GetKopie
      End Sub


      <Serializable()> Public MustInherit Class BasisKlasse
        Public Guid As String
        Public GuidVorlage As String
      End Class


      <Serializable()> Public MustInherit Class BasisKlasse_Derived(Of clsDerivedClass_TP As BasisKlasse)
        Inherits BasisKlasse

        Public Function GetKopie() As clsDerivedClass_TP
          Dim kopie As BasisKlasse = GetDuplikat(Me)
          kopie.GuidVorlage = Me.Guid
          Return DirectCast(kopie, clsDerivedClass_TP)
        End Function
      End Class


      <Serializable()> Public Class KlasseA
        Inherits BasisKlasse_Derived(Of KlasseA)
      End Class

      <Serializable()> Public Class KlasseB
        Inherits BasisKlasse_Derived(Of KlasseB)
      End Class


      Public Function GetDuplikat(Of T)(ByVal obj As T) As T
        Dim memoStream = New System.IO.MemoryStream
        Dim binFormatter = New Runtime.Serialization.Formatters.Binary.BinaryFormatter
        binFormatter.Serialize(memoStream, obj)
        memoStream.Position = 0
        Return CType(binFormatter.Deserialize(memoStream), T)
      End Function
    End Module



    Donnerstag, 5. Juli 2012 19:56
  • Hallo Markus,

    leider funktioniert das nicht

    ...Dim kopie As BasisKlasse = GetDuplikat(Me) ...:  Hier kommt die Fehlermeldung "Der Verweis auf einen nicht freigegebenen Member erfordert einen Objektverweis".

    Ich vermute, dass es auch ohnehin nicht funktionieren würde, da "Dim kopie As BasisKlasse" das Objekt ja nur als Basisklasse definieren würde. Die KlasseA, KlasseB .. werden ja noch um etliche Member erweitert, die dann fehlen würden.

    Ich vermute der elegante Lösungsansatz ist irgendwie Generisch gelagert (ähnlich "Function GetDuplikat"), aber irgendwie hab ich hier noch nicht die Lösung gefunden. Ich hab im Moment mit der Überladung das Kopieren funktionsfähig implementiert, es ist für mich trotzdem eine kleine Herausforderung eine generische Lösung zu finden (falls möglich).

    Gruß Peter


    Peter

    Freitag, 6. Juli 2012 15:47
  • Dieser Ansatz ist generisch. Er gibt KlasseA und KlasseB als Typparameter an die Basisklasse.

    In Sub Main könnte objA1 auch direkt als KlasseA deklariert werden. Das wäre auch klarerer Code.

      Public Sub Main()
        Dim objA As New KlasseA
        Dim objB As New KlasseB

        ' objA.GetKopie in der gemeinsamen BasisKlasse_Derived hat hier einen Rückgabewert vom Typ
        ' KlasseA.
        ' Dim objB1 As KlasseB = objA.GetKopie würde eine Fehlermeldung erzeugen.
        ' Value of type 'WindowsApplication1.Module1.KlasseA' cannot be converted to  
        ' WindowsApplication1.Module1.KlasseB'.

        Dim objA1 As KlasseA = objA.GetKopie
       
        ' objB.GetKopie in der gemeinsamen BasisKlasse_Derived hat hier einen Rückgabewert vom Typ
        ' KlasseB.
        Dim objB1 As KlasseB = objB.GetKopie
      End Sub


    Me in GetKopie verweist auf eine KlasseA oder KlasseB Instanz (also Klasseninstnz = Objekt). GetKopie gibt ein KlasseA oder KlasseB Objekt zurück. kopie es ist zwar mit Basisklasse definiert. Ist aber im Fall oben ein Zeiger auf  das kopierte neue KlasseA oder KlasseB Objekt. Sonst ginge der DirectCast nicht in der Return Anweisung.


    Du kannst dort einen Breakpoint setzen und im Debug wird dir der Klassenname angezeigt wenn du mit der Maus auf Me zeigst.

    MyClass würde auf die Baisisklasse Intanz verweisen.

    Ich habe oben in KlasseA bei mir dann noch ein Private Test As String = "Test1".
    Diese Variable war dann so auch in der Kopie ObjA1 vorhanden.

    Bei mir erscheint keine Fehlermeldung. Option explicit habe ich auf On. Option Strict On. Option
    infer On.

    Du könntest das Beispiel ja mal exakt so in ein Modul kopieren und schauen ob es dann funktioniert.
    Würde dir auch vorschlagen das Beispiel dann schrittweise zu debuggen und mit der Maus in jeder Zeile auf die Variablennamen zu zeigen so dass du ihren Datentyp siehst. Oder du lässt dir das Locals Windows anzeigen. Das ist komfortabler.

    Vermute das der Ort von GetDuplikat der Grund für die Fehlermeldung ist. Du könntest diese Funktion in eine separate Klasse ausgliedern und Shared deklarieren. Z.B. clsCopyFunctions. Der Aufruf wäre dann direkt über die Klasse clsCopyFunctions.GetKopie. D.h. ein CopyFunctions Objekt ist nicht nötig.




    • Bearbeitet Markus222 Freitag, 6. Juli 2012 17:16
    Freitag, 6. Juli 2012 16:36
  • Die methode GetDuplikat() muss in die BasisKlasse_derived und kann dort dann auch noch als private rein. Es funktioniert, wie in der Sub Main von Markus beschrieben.

    Hannes

    If you have got questions about this, just ask.

    In a perfect world,
    users would never enter data in the wrong form,
    files they choose to open would always exist
    and code would never have bugs.

    C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/

    Freitag, 6. Juli 2012 17:19
  • In der Tat, so funktioniert es! PS ging aber nicht mit GetDuplikat private sondern public

    Wunderbar und merci!

    Peter


    Peter

    Freitag, 6. Juli 2012 18:39