代码之家  ›  专栏  ›  技术社区  ›  arynaq

DataContractSerializer,将T的序列化附加到列表的序列化<T>

  •  1
  • arynaq  · 技术社区  · 7 年前

    为了学习,我试图抽象出db访问,希望能够插入一个XML文件或JSON文件来提供数据访问。

    现在我的类型有以下构造函数

    public XmlRepository(XElement root)
    {
            _rootElement = root;
            Load();
    }
    

    依赖项(根)由如下XmlContext类型提供:

    private void Load()
        {
            if (!File.Exists(_fileName))
            {
                var schoolsXElement = new XElement("Schools");
                var gradesXElement = new XElement("Grades");
                var teachersXElement = new XElement("Teachers");
                var studentsXElement = new XElement("Students");
    
                _document = new XDocument(new XElement("DB"));
                _document.Root.Add(schoolsXElement);
                _document.Root.Add(gradesXElement);
                _document.Root.Add(teachersXElement);
                _document.Root.Add(studentsXElement);
                using (var fs = new FileStream(_fileName, FileMode.Create))
                {
                    _document.Save(fs);
                }
    
            }
            else
            {
                _document = XDocument.Load(_fileName);
            }
    
            Schools = new XmlRepository<School>(_document.Root.Element("Schools"));
            Grades = new XmlRepository<Grade>(_document.Root.Element("Grades"));
            Teachers = new XmlRepository<Teacher>(_document.Root.Element("Teachers"));
            Students = new XmlRepository<Student>(_document.Root.Element("Students"));
        }
    

    这些方法在中定义 XmlRepository<T> 当要将对数据的内存中视图的更改持久化到文件时,可以调用。

    private void Load()
        {
            if (!_rootElement.HasElements)
            {
                _persistentStorage = new List<T>();
                _memoryStorage = new List<T>();
                return;
            }
    
            var xmlDeserializer = new DataContractSerializer(typeof(List<T>));
            var obj = xmlDeserializer.ReadObject(_rootElement.FirstNode.CreateReader()) as List<T>;
            _persistentStorage = new List<T>(obj);
            _memoryStorage = new List<T>(obj);
        }
    
        private void Save()
        {
            var xmlSerializer = new DataContractSerializer(typeof(List<T>));
            var newAdditions = _memoryStorage.Except(_persistentStorage).ToList();
            _persistentStorage.AddRange(newAdditions);
            _rootElement.RemoveAll();
            using (var fs = _rootElement.CreateWriter())
            {
                xmlSerializer.WriteObject(fs, _persistentStorage);
            }
        }
    
    private void Save()
        {
            var xmlSerializer = new DataContractSerializer(typeof(List<T>));
            var newAdditions = _memoryStorage.Except(_persistentStorage).ToList();
            _persistentStorage.AddRange(newAdditions);
            _rootElement.RemoveAll();
            using (var fs = _rootElement.CreateWriter())
            {
                xmlSerializer.WriteObject(fs, _persistentStorage);
            }
        }
    

    <?xml version="1.0" encoding="utf-8"?>
    <DB>
      <Schools>
        <ArrayOfSchool xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models" />
      </Schools>
      <Grades>
        <ArrayOfClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="LearningProject.Models">
          <Class>
            <Id xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models">0</Id>
            <Grade>126368128361</Grade>
            <Students xmlns:d3p1="http://schemas.datacontract.org/2004/07/LearningProject.Models" i:nil="true" />
            <Teacher i:nil="true" />
          </Class>
          <Class>
            <Id xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models">1</Id>
            <Grade>126368128361</Grade>
            <Students xmlns:d3p1="http://schemas.datacontract.org/2004/07/LearningProject.Models" i:nil="true" />
            <Teacher i:nil="true" />
          </Class>
        </ArrayOfClass>
      </Grades>
      <Teachers>
        <ArrayOfTeacher xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models" />
      </Teachers>
      <Students>
        <ArrayOfStudent xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models" />
      </Students>
    </DB>
    

    现在我的问题是save方法,我不喜欢删除存在的内容并用持久存储中的内容替换它。假设我有10K个元素,只添加了1个,我会删除10K个元素,只为了再添加1个。

    我该如何改为附加到XML?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Marc Gravell    7 年前

    像xml这样的格式根本不利于附加,并且没有标准的xml序列化程序支持您想要做的事情。

    为了避免数据丢失的风险,您可以加载现有数据、添加新对象、序列化 到另一个文件

    还有其他更友好的格式。例如,protobuf不终止根元素,因此如果您有如下形式的消息:

    message SomeRoot {
        repeated SomeType items = 1;
    }
    

    第二 SomeRoot 带5个 SomeType 与3 项目是 完全相同的 与8 项目。