0

Моего NetDataContractSerializer кажется спутать: Конец XML появляется дважды:NetDataContractSerializer производит недопустимый XML

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="1" 

[...] 
     <d2p1:anyType i:nil="true" /> 
     </d2p1:_items> 
     <d2p1:_size>2</d2p1:_size> 
     <d2p1:_version>2</d2p1:_version> 
    </d2p1:items> 
    </ProjectParts> 
    <ProjectPath z:Id="31">D:\t10\</ProjectPath> 
</Project>ze> 
       <d2p1:_version>3</d2p1:_version> 
      </d2p1:items> 
      <d2p1:_monitor xmlns:d7p1="http://schemas.datacontract.org/2004/07/System.Collections.ObjectModel" z:Id="33"> 
       <d7p1:_busyCount>0</d7p1:_busyCount> 
      </d2p1:_monitor> 
      </Elements> 
      <Project z:Ref="1" i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/Modules.WorkspaceManager.Types" /> 
     </d2p1:anyType> 
     <d2p1:anyType i:nil="true" /> 
     <d2p1:anyType i:nil="true" /> 
     </d2p1:_items> 
     <d2p1:_size>2</d2p1:_size> 
     <d2p1:_version>2</d2p1:_version> 
    </d2p1:items> 
    </ProjectParts> 
    <ProjectPath z:Id="34">D:\t10\</ProjectPath> 
</Project> 

Как вы можете видеть, есть некоторое серьезное заикание происходит. Это случается иногда, и я не могу воспроизвести ошибку. Есть идеи? Может ли это быть вызвано открытием файла в VS во время его написания?

сериализовать мой объект, как это:

private void SerializeToFile(object objectToSerialize) 
    { 
     Stream stream = null; 

     try 
     { 
      stream = File.Open(_fileName, FileMode.OpenOrCreate, FileAccess.Write); 
      using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) 
      { 
       NetDataContractSerializer serializer = new NetDataContractSerializer(); 
       serializer.WriteObject(writer, objectToSerialize); 
      } 
     } 

     finally 
     { 
      if (stream != null) stream.Close(); 
     } 
    } 

А класса сериализованные выглядит так:

[DataContract(IsReference = true)] 
public class Project : IProject 
{ 
    [DataMember] public string ProjectPath { get; set; } 
    [DataMember] public string ProjectName { get; set; } 
    [DataMember] public Collection<IProjectPart> ProjectParts { get; set; } 

    public T GetPart<T>() where T : IProjectPart 
    { 
     return ProjectParts.OfType<T>().First(); 
    } 

    public void RegisterPart<T>(T part) where T : IProjectPart 
    { 
     if (ProjectParts.Any(p => p.GetType().IsInstanceOfType(part))) throw new InvalidOperationException("Part already registered."); 
     ProjectParts.Add(part); 
     part.Project = this; 
    } 

    public void Load() 
    { 
     foreach (var projectPart in ProjectParts) 
     { 
      projectPart.Load(); 
     } 
    } 

    public void Unload() 
    { 
     foreach (var projectPart in ProjectParts) 
     { 
      projectPart.Unload(); 
     } 
    } 

    public void Save() 
    { 
     foreach (var projectPart in ProjectParts) 
     { 
      projectPart.Save(); 
     } 
    } 

    public Project() 
    { 
     ProjectParts = new Collection<IProjectPart>(); 
    } 
} 

Спасибо!

+0

может вы публикуете класс, который вы пытаетесь сделать сериализацией, и как вы это делаете, и т. д.? – tchrikch

+0

@tchrikch: Смотрите мое редактирование. Спасибо за замечание. – Marc

ответ

1

Проблема проста - при сериализации многократно и более, вы делаете это с разным размером коллекции IProjectPart. Метод File.Open не удаляет файл из предыдущего содержания, так предположим следующие шаги:

I) сериализовать объект с двумя IProjectPart instaces - скажем, это займет 10 строк файла XML

II) сериализовать объект снова один IProjectPart экземпляр в коллекции - на этот раз это займет 8 строк xml-файла

iii) строки 9 и 10 будут заполнены старыми данными xml, так как они не очищаются между попытками сериализации - так что есть несколько дубликатов- xml данные.

Попробуйте сами, вы увидите, как именно генерируются эти несколько тегов.

Примечание: 8 и 10 строк имеют приблизительные значения для моей реализации

Примечание 2: Я предлагаю использовать using заявление для потока внутри метода сериализации (как и для всех IDisposable объектов):

private void SerializeToFile(object objectToSerialize) 
{ 
    using(var stream = File.Open(_fileName, FileMode.OpenOrCreate, FileAccess.Write)) 
    { 
     using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) 
     { 
      NetDataContractSerializer serializer = new NetDataContractSerializer(); 
      serializer.WriteObject(writer, objectToSerialize); 
     } 
    } 
} 
+0

AH! Спасибо! Я исправил его, очистив файл с помощью File.WriteAllText (_fileName, string.Empty); ... Большое спасибо! – Marc

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