2015-01-13 3 views
2

Я работаю над проектом, для которого потребуется функция сохранения/загрузки. Я смотрю на два возможных способах:классы сериализации vb.net

  • сделать свои собственные функции, которые делают сохранение/загрузку => делает мое «собственное» filestructure держать все на месте (очень много работы)
  • использования сериализации некоторых kind

В моем текущем тестовом проекте я реализовал сериализацию, но когда я обновляю класс, весь проект нечитабелен, потому что он не может быть обработан десериализацией ... Сделать его очень трудно использовать, если я хочу файлы для обратной совместимости.

На данный момент я использую этот подход:

<System.Serializable()> _ 
Public MustInherit Class clsCompo 
    Implements ISerializable 

    ... 

    Public Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializable.GetObjectData 
     info.AddValue("properties", Me._properties, GetType(CustomPropertyCollection)) 
    End Sub 

    Public Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext) 
     Me._properties = DirectCast(info.GetValue("properties", GetType(CustomPropertyCollection)), CustomPropertyCollection) 
    End Sub 
End Class 

Я совсем потерял во всем этом, потому что я считаю, что это трудно обрабатывать, особенно при использовании более чем 30 различных классов, которые все должны быть сериализации.

То, что я на самом деле после того, как точка в «хорошей» направления для реализации функции Save/Load, которая может быть обратной совместимостью и может сохранять различные классы в одном файле

EDIT: В конце концов, я нашел проект, аналогичный тому, что мне было нужно: http://www.codeproject.com/Articles/30270/XML-Serialization-of-Complex-NET-Objects

Это похоже на то, что было опубликовано ниже.

+0

Десуриализация в измененный класс является проблемой только с BinaryFormatter. XMLSerialization и ProtoBuf-NET не имеют этой проблемы. – Plutonix

ответ

0

Вам необходимо разработать свой доступ к данным, который вы получаете xml из хранимых процедур и поток в свои объекты через свой DAL. Затем возьмите данные хранимой процедуры xml и преобразуйте их в объект.

Dim OBJ как новое YourObjectType

OBJ = ConvertFromXml (XML.toString(), GetType (YourObjectType), System.Text.Encoding.UTF8)

Public Shared Function ConvertFromXml(ByVal xml As String, ByVal objType As System.Type, ByVal encoding As System.Text.Encoding) As Object 

    Dim o As Object = Nothing 


    Dim serializer As XmlSerializer = New XmlSerializer(objType) 
    Using ms As MemoryStream = New MemoryStream(encoding.GetBytes(xml)) 
     Using xr As XmlTextReader = New XmlTextReader(ms) 
      o = serializer.Deserialize(xr) 
     End Using 
    End Using 



    Return o 
End Function 
2

Самый простой метод, который я имел разумные долгосрочные результаты заключаются в том, чтобы обеспечить (в настоящее время и навсегда) ваш собственный контракт, что каждый класс имеет как минимум свойство Версии, которое в сочетании с типом дает вам уникальный идентификатор, чтобы позже рассказать вам, как десериализовать объект.Вы также можете создавать объекты из разных классов в зависимости от версии # ваших сохраненных данных, поэтому не выполняйте управление версиями внутри класса, сделайте это, например, с помощью объекта Persister, который работает на любом объекте, реализующем ваш интерфейс с состоянием:

Сначала используйте прикладную шириной Enum для основных типов вашего приложения объекта (не каждый класс):

Public Enum MyObjectTypesEnum 
    Unspecified = 0 
    Fish = 1 
    Cow = 2 
End Enum 

Тогда ваш интерфейс:

Public Interface IStateful 
    ReadOnly Property Version As Integer 
    ReadOnly Property ObjectType As MyObjectTypesEnum 
    Sub SetState(Info As SerializationInfo) 
    Sub GetState(Info As SerializationInfo) 
End Interface 

Шаг 1 в сохраняющихся свои объекты для хранения версии и введите:

Public Sub SaveTheBasics(Info As SerializationInfo, TheObject as IStateful) 
    Info.SetInt64(TheObject.Version,"Version") 
    Info.SetInt64(TheObject.ObjectType,"ObjectType") 

Это хранит всю необходимую информацию, чтобы справиться с различными версиями в будущем:

Dim TheObject as IStateful 

Select Case Info.GetInt64("ObjectType") 
Case MyObjectTypesEnum.Fish 
    Select Case Info.GetInt64("Version") 
    Case Is < 2 
     TheObject = New OldestFishClass 
    Case Is < 5 
     TheObject = New OldFishClass 
    Case Else 
     TheObject = New NewFishClass 
    End Select 
Case MyObjectTypesEnum.Cow 
    ... 
End Select 
TheObject.SetState(Info) 

etc etc. 

Если политика вашего приложения является настоять данные хранятся в самой последней версии, то при загрузке и обновление данных предыдущей версии, вы можете создать экземпляр старого класса, и использовать это в перегруженном методе загрузки вашего новейших класса обновление:

Select Case Info.GetInt64("Version") 
    ... 
    Case Is < 5 
     Dim TempOldObject As New OldFishClass 
     TempOldObject.SetState(Info) 
     TheObject = New NewFishClass 
     TheObject.SetState(TempOldObject) 
    Case Else 
     TheObject = New NewFishClass 
     TheObject.SetState(Info) 
    End Select 
    ...   

... и убедитесь, что у наш новый класс знает, как загрузить его предыдущую версию, как показано ниже.

Вы можете использовать базовый класс, который реализует интерфейс для всех сохраняющих состояние объектов, а также имеет все свойства, все ваши объекты, возможно, потребуется:

Public MustInherit Class MyBaseClass 
    Implements IStateful 
    Public MustOverride Readonly Property VersionNumber As Integer Implements IStateful.Version 
    Public MustOverride Readonly Property ObjectType As MyObjectTypesEnum Implements IStateful.ObjectType 
    Public UniqueID As GUID 

... 

Public Class NewFishClass 
    Inherits MyBaseClass 
    Public Overrides ReadOnly Property VersionNumber As Integer 
     Get 
     Return 5 
     End Get 
    End Property 
    Public Overrides ReadOnly Property ObjectType As MyObjectTypesEnum 
     Get 
     Return MyObjectTypesEnum.Fish 
     End Get 
    End Property 
    'Overloaded state-setting methods (could be Constructors instead): 
    Public Sub SetState(Info As SerializationInfo) 
     Me.ScaleCount = Info.GetInt64("ScaleCount") 
    End Sub 
    Public Sub SetState(OldFish As OldFishClass) 
     'Upgrade from V2: 
     Me.ScaleCount = OldFish.LeftScales + OldFish.RightScales 
    End Sub 
    Public Sub SetState(OldestFish As OldestFishClass) 
     'Upgrade from V1 
     Me.ScaleCount = OldFish.Length * OldFish.ScalesPerUnitLength) 
    End Sub 
etc etc. 

Главный принцип здесь в том, что договор содержится в интерфейсах , и, насколько это возможно, базовый класс выполняет необходимую работу по выполнению этого контракта. Затем для создания 30 классов вы наследуете каждого из базового объекта. Если вы построили его правильно, вы будете вынуждены предоставить информацию, необходимую для правильного управления версиями и устойчивости (вы также создаете слои абстракции, которые, конечно же, в какой-то момент вы будете благодарны).

В больших проектах я расширяю такое мышление, чтобы сохраняемые свойства каждого объекта содержались в объекте «State», который происходит из базового класса StateBase, который сам реализует интерфейс IState. Затем Persistance действует на любой объект StateBase. Я также использую класс CollectionBase (который также наследует от моего базового класса), который обрабатывает экземпляр и заполнение содержащихся объектов. Часто вашим объектам необходимо хранить ссылки друг на друга через сеансы, поэтому для восстановления этих ссылок требуется уникальный идентификатор (GUID), который входит в базовый объект.

+0

Я работаю над этим, но не понимаю эту идею. Таким образом, вы загружаете номер версии и в зависимости от этой версии вы инициализируете класс, который обрабатывает эти данные? Поэтому, чтобы использовать новую версию класса, я должен «перевести» старые данные в новый класс и сохранить его с новым классом. Можете ли вы предоставить небольшой тестовый проект, иллюстрирующий ваш рабочий процесс по крупным проектам? Думаю, я могу пойти по этому пути. – Incubus

+0

После того, как все это работает, скорее всего, это не так «мало» по некоторым стандартам, есть справедливая часть кодирования, что является наказанием за гибкость. Как обрабатывать обновление зависит от политики жизненного цикла вашего приложения: как только вы устанавливаете версию 2, автоматически ли она сохраняет данные V1 в формате V2? Или вы продолжаете использовать объекты V1 и т. Д.? При обновлении каждый класс и код сохранения должны быть изменены. Я немного отредактирую свой ответ. – HeyHeyJC

+0

Этот вопрос объясняет немного больше вопросов, связанных со ссылками - я согласен с принятым ответом.[Ссылка] (http://stackoverflow.com/questions/2026238/net-xmlserializer-and-multiple-references-to-the-same-object). Методология, которую я использую, заключается в объединении всех объектов по идентификатору (GUID) в глобальном словаре во время десериализации, а затем пересечении всей модели, снова воссоздающей ссылки на объекты. – HeyHeyJC

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