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>();
}
}
Спасибо!
1 ответ
Проблема проста - когда вы сериализуете снова и снова ваш объект, вы делаете это с другим размером IProjectPart
коллекция. File.Open
Метод не удаляет файл из предыдущего содержимого, поэтому примите следующие шаги:
я) сериализовать объект с двумя IProjectPart
instaces - скажем, это займет 10 строк XML-файла
ii) снова сериализовать объект одним IProjectPart
экземпляр в коллекции - на этот раз он займет 8 строк XML-файла
iii) строки 9 и 10 будут заполнены старыми данными 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);
}
}
}