2016-12-11 2 views
1

Я обнаружил, что у многих людей такая же проблема, но я не нашел, как это исправить.Ошибка при сериализации класса, содержащего List (Of OtherClass)

Предположим, что у меня есть 2 классов Employee и Department

Employee

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 

Департамент класса

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 

Когда я побежал следующий код

 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") 

я получил исключение на ml1.WriteToXml("1.xml")

Был ошибку, отражающий тип 'SerializerTest.Department'

Проблема заключается в том, что Department Класс содержит List(of Employee)

Я нашел многие статьи говорят об этой проблеме, но я не знаю, как это сделать.

+1

Вам не нужно 'Serializable' атрибут, если вы дело только с XML-сериализации. Он используется для двоичной сериализации. –

+2

Этот класс Employee не является сериализуемым, так как он не имеет простого ctor, нет причины в * том, чтобы сериализовать Депозит, а просто сериализовать список Employee, если были некоторые реквизиты Dept (например, даже Name), своего рода глупый создать внутренний объект и скопировать элементы в Меня. Просто сделайте это Shared методом, возвращающим объект Department ... и CrytoStream может быть лучше/проще, чем этот крипто-метод. – Plutonix

+2

@VisualVincent также необходим для сериализации дизайнера – Plutonix

ответ

1

Передовая проблема заключается в том, что Employee не имеет конструктора без параметров:

Public Class Employee 

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

    Public Sub New() 

    End Sub 
    ... 

Но методы сериализации немного расточительны. При десериализации, а не копировать все данные из внутреннего, объекта темп в Me, вы можете сделать это метод Shared, чтобы создать и вернуть объект, который будет использоваться приложением:

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 

Затем создать/загрузить объект Департамент с помощью этого метода:

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 

Все мои сотрудники сделали кругосветное путешествие:

Зигги
Zoey
пылесосить

Смежные вопросы