2016-12-11 3 views
1

Ich fand, dass viele Leute das gleiche Problem haben, aber ich habe nicht gefunden, wie man es repariert.Fehler beim Serialisieren der Klasse, die List (Of OtherClass) enthält

Angenommen, ich habe 2 Klassen Employee und Department

Mitarbeiter

Imports System.ComponentModel 
Public Class Employee 
    Public Property Name As String 
    Public Property LastName As String 
    Public Property MotherName As String 

    Public Sub New(ByVal str1, ByVal str2, ByVal str3) 
     Name = str1 
     LastName = str2 
     MotherName = str3 
    End Sub 
End Class 

Abteilung Klasse

Public Class Department 
    Public Property Employees As List(Of Employee) 

    Public Sub New() 
     Employees = New List(Of Employee) 
    End Sub 

    Public Sub WriteToXml(ByVal strXmlFilePath As String, 
          Optional ByVal encrypted As Boolean = False) 
     Dim xs As New Serialization.XmlSerializer(GetType(Department)) 
     Dim sr As New StringWriter 
     Dim strObject As String = String.Empty 

     xs.Serialize(sr, Me) 

     If encrypted Then 
      Dim wrapper As Simple3Des = New Simple3Des("123") 
      strObject = wrapper.EncryptData(sr.ToString) 
     Else 
      strObject = sr.ToString 
     End If 

     Using sw As New StreamWriter(strXmlFilePath) 
      sw.Write(strObject) 
      sw.Close() 
     End Using 
    End Sub 

    Public Sub ReadFromXml(ByVal strXmlFilePath As String, 
          Optional ByVal encrypted As Boolean = False) 
     Dim xs As New Serialization.XmlSerializer(GetType(Department)) 
     Dim strObject As String = String.Empty 
     Dim micResult As New Department 

     Using sr As New StreamReader(strXmlFilePath) 
      strObject = sr.ReadToEnd 

      If encrypted Then 
       Dim wrapper As Simple3Des = New Simple3Des("123") 
       strObject = wrapper.DecryptData(strObject) 
      End If 

      sr.Close() 
     End Using 

     micResult = DirectCast(xs.Deserialize(New StringReader(strObject)), Department) 
     Me.Employees.AddRange(micResult.Employees) 
     micResult.Dispose() 
    End Sub 

Wenn ich den folgenden Code lief

 Dim m As New Employee("A", "B", "C") 
     Dim m1 As New Employee("D", "E", "F") 
     Dim ml1 As New Department 
     Dim ml2 As New Department 

     ml1.Employees.Add(m) 
     ml1.Employees.Add(m1) 

     ml1.WriteToXml("1.xml") 

bekam ich eine Ausnahme auf ml1.WriteToXml("1.xml")

Es wurde ein Fehler Typ reflektieren 'SerializerTest.Department'

Das Problem ist, dass Department Klasse ein List(of Employee)

enthält gefunden viele Artikel sprechen über dieses Problem, aber ich weiß nicht, wie ich das erreichen soll.

+1

Sie brauchen nicht die 'Serializable' Attribut, wenn Sie nur mit XML-Serialisierung zu tun. Es wird für die binäre Serialisierung verwendet. –

+2

Diese Mitarbeiterklasse ist nicht serialisierbar, da sie kein einfaches ctor hat, es gibt keinen Grund in * dem *, das Departement zu serialisieren - sondern nur die Mitarbeiterliste zu serialisieren, wenn es Dept-Requisiten (wie zB einen Namen) gibt um ein inneres Objekt zu erstellen und die Elemente zu mir zu kopieren. Machen Sie es einfach zu einer Shared-Methode, die das Department-Objekt zurückgibt ... und ein CrytoStream könnte besser/einfacher sein als diese Crypto-Methode. – Plutonix

+2

@VisualVincent es ist auch für Designer-Serialisierung benötigt – Plutonix

Antwort

1

Das vorderste Problem ist, dass Employee nicht einen parameterlosen Konstruktor hat:

Public Class Employee 

    Public Property Name As String 
    Public Property LastName As String 
    Public Property MotherName As String 

    Public Sub New() 

    End Sub 
    ... 

Aber die Serialisierungsmethoden ein bisschen verschwenderisch sind. Wenn Deserialisieren, anstatt alle Daten aus einem internen zu kopieren, Temperatur Objekt Me, können Sie es eine Shared Methode machen, um das Objekt zu erstellen und zum von der App verwendet werden:

Public Class Department 
    ... 
    Public Shared Function Load(strXmlFilePath As String) As Department 
     Dim xs As New Serialization.XmlSerializer(GetType(Department)) 
     ' ToDo: return Nothing if file DNE 
     Using fs As New FileStream(strXmlFilePath, FileMode.Open) 
      Dim d As Department 
      d = xs.Deserialize(fs) 
      Return d 
     End Using 

    End Function 

Dann erstellen/laden die Abteilung Objekt mit dieser Methode:

Dim d As New Department 
d.Employees.Add(New Employee("ziggy", "jones", "")) 
d.Employees.Add(New Employee("zoey", "smith", "")) 
d.Employees.Add(New Employee("hoover", "greene", "q")) 

d.WriteToXml("C:\Temp\Depts.xml") 

Dim d2 = Department.Load("C:\Temp\Depts.xml") 
'd2.ReadFromXml("C:\Temp\Depts.xml") 

For Each emp In d2.Employees 
    Console.WriteLine(emp.Name) 
Next 

Alle meine Mitarbeiter machte die Rundreise:

ziggy
Zoey
staubsauger

Verwandte Themen