0

I'm having real problems implementing Deep Copy on my custom data objects. I've tried various approaches I've found through StackOverflow, but having problems with all of them. I've tried various serialise/deserialise approaches (but not json, as I figure the problems I have would also occur in this) plus reflection methods. All have their issues. Here's my most recent code:

<Serializable>
Public Class Element

    <NonSerialized>
    Public AssociatedComponent As WinFormsDesigner.Component = Nothing

    <Browsable(False)>
    Public Property IsRigControl As Boolean = False

    Public Property ID As ObjectId = ObjectId.NewObjectId
    <GridSort("General", 10), Description("Order of element in layout with 0 being bottommost. Set via the Element Selector."), [ReadOnly](True)>
    Public Property ZIndex As Integer = 0
    
    <GridSort("General", 10)>
    Public Property Size As Size = New Size(120, 60)
    
    ' Various Properties - all of standard value types: string, integer, Enums, List(of standard value types)

End Class

<TypeConverter(GetType(CustomClassDropDownConverter))>
<Serializable>
Public Class TextElement
    Inherits Element

    Public ObjectName As String = "Text Element"
    <IgnoreDataMember>
    Public ObjectIcon As Image = My.Resources.TextStyles

    ' Operational
    Public LastCycled As Date

    <GridSort("General", 10)>
    Public Property Name As String = "{New Text}"

    ' Various Properties - all of standard value types: string, integer, Enums, List(of standard value types)

    Public Overrides Function ToString() As String
        Return Name & ControlChars.NullChar & "(" & ID.ToString & ")"
    End Function

End Class

Module DeepClone

    <Extension>
    Public Function DeepClone(Of T)(ByVal obj As T) As T
        Using ms = New MemoryStream()
            Dim formatter = New BinaryFormatter()
            formatter.Serialize(ms, obj)
            ms.Position = 0
            Return CType(formatter.Deserialize(ms), T)
        End Using
    End Function

End Module

This results in:

System.Runtime.Serialization.SerializationException: 'Type 'LiteDB.ObjectId' in Assembly 'LiteDB, Version=4.1.4.0, Culture=neutral, PublicKeyToken=4ee40123013c9f27' is not marked as serializable.'

I do want to be able to copy the ID too, however, changed the ID fields to this to enable putting NonSerilizable on the private member:

  <NonSerialized>
    Private _id As ObjectId = ObjectId.NewObjectId

    <Browsable(False)>
    <GridSort("General", 10), [ReadOnly](True)>
    Public Property ID() As ObjectId
        Get
            Return _id
        End Get
        Set(ByVal value As ObjectId)
            _id = value
        End Set
    End Property

However, now get:

System.Runtime.Serialization.SerializationException: 'Unable to find assembly 'Infoz, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null'.'

Infoz is my main assembly.

Another unchangeable restricting factor is that I'm developing on Framework 3.5.

I've also tried the various reflection approaches suggested on SO, but again, no joy. I'm afraid I've lost track on what I've tried and the resulting errors, so am hoping my scenario will be enough for someone to know how to help.

I did try a very popular SO solution here but got a runtime exception in the GetHashCode Override:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

I'm not fussy about how I achieve it (a specific library, reflection, serialisation etc) as it's not a heavy iterative operation, I just need to achieve it! It's interesting how something so fundamental as copying data objects can be so tricky!

stigzler
  • 793
  • 2
  • 12
  • 29
  • `unchangeable restricting factor is that I'm developing on Framework 3.5.` why? the only reason for this would be targeting unsupported Windows versions like XP or Server 2003. – Panagiotis Kanavos Feb 10 '22 at 11:52
  • As for the actual problem, just don't use serialization for deep copying. You could create a deep copy by explicitly creating the objects and assigning their properties. Serialization is used as a *very* expensive method of avoiding the handwritten code. You could use eg AutoMapper instead to get rid of the extra code. The answers to [Copy object to object with Automapper?](https://stackoverflow.com/questions/5713556/copy-object-to-object-with-automapper) show how to do this. Once you configure mappings for all types, you can use `var person1=mapper.Map(person2);` – Panagiotis Kanavos Feb 10 '22 at 11:58

0 Answers0