Как включить несколько файлов XML в один файл XML для десериализации с помощью XmlSerializer в .NET - PullRequest
0 голосов
/ 12 февраля 2010

возможно ли использовать XmlSerializer в .NET для загрузки файла XML, который включает другие файлы XML? И как?

Это для того, чтобы легко обмениваться XML-состоянием в двух «родительских» XML-файлах, например, AB и BC ниже.

Пример:

using System;
using System.IO;
using System.Xml.Serialization;

namespace XmlSerializerMultipleFilesTest
{
    [Serializable]
    public class A
    {
        public int Value
        { get; set; }
    }

    [Serializable]
    public class B
    {
        public double Value
        { get; set; }
    }

    [Serializable]
    public class C
    {
        public string Value
        { get; set; }
    }

    [Serializable]
    public class AB
    {
        public A A
        { get; set; }
        public B B
        { get; set; }
    }

    [Serializable]
    public class BC
    {
        public B B
        { get; set; }
        public C C
        { get; set; }
    }

    class Program
    {
        public static void Serialize<T>(T data, string filePath)
        {
            using (var writer = new StreamWriter(filePath))
            {
                var xmlSerializer = new XmlSerializer(typeof(T));
                xmlSerializer.Serialize(writer, data);
            }
        }
        public static T Deserialize<T>(string filePath)
        {
            using (var reader = new StreamReader(filePath))
            {
                var xmlSerializer = new XmlSerializer(typeof(T));
                return (T)xmlSerializer.Deserialize(reader);
            }
        }

        static void Main(string[] args)
        {
            const string fileNameA = @"A.xml";
            const string fileNameB = @"B.xml";
            const string fileNameC = @"C.xml";

            const string fileNameAB = @"AB.xml";
            const string fileNameBC = @"BC.xml";

            var a = new A(){ Value = 42 };
            var b = new B(){ Value = Math.PI };
            var c = new C(){ Value = "Something rotten" };

            Serialize(a, fileNameA);
            Serialize(b, fileNameB);
            Serialize(c, fileNameC);

            // How can AB and BC be deserialized from single 
            // files which include two of the A, B or C files.
            // Using ideally something like:
            var ab = Deserialize<AB>(fileNameAB);
            var bc = Deserialize<BC>(fileNameBC);
            // That is, so that A, B, C xml file 
            // contents are shared across these two
        }
    }
}

Таким образом, файлы A, B, C содержат следующее:

A.xml:

<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Value>42</Value>
</A>

B.xml:

<?xml version="1.0" encoding="utf-8"?>
<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Value>3.1415926535897931</Value>
</B>

C.xml:

<?xml version="1.0" encoding="utf-8"?>
<C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Value>Something rotten</Value>
</C>

И тогда «родительские» XML-файлы будут содержать какой-либо XML-файл включения (я не смог найти ничего подобного), например:

AB.xml

<?xml version="1.0" encoding="utf-8"?>
<AB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <A include="A.xml"/>
  <B include="B.xml"/>
</AB>

BC.xml:

<?xml version="1.0" encoding="utf-8"?>
<BC xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <B include="B.xml"/>
  <C include="C.xml"/>
</BC>

Конечно, я думаю, что это можно решить путем реализации IXmlSerializer для AB и BC, но я надеялся, что найдется более простое решение или универсальное решение, для которого самим классам нужен только атрибут [Serializable] и больше ничего. То есть разделение на несколько файлов осуществляется только в формате XML и обрабатывается самим XmlSerializer или пользовательским универсальным сериализатором поверх этого.

Я знаю, что это должно быть несколько возможно с app.config (как в Использование XML включает или ссылки на конфигурацию в app.config для включения настроек других файлов конфигурации ), но я бы предпочел решение на основе XmlSerializer.

Спасибо.

1 Ответ

1 голос
/ 12 февраля 2010

Короткий ответ - да, это возможно без реализации IXmlSerializer. Но это действительно некрасиво. Вероятно, хуже, чем реализация IXmlSerializer. Проверьте это, чтобы начать. Он включает запуск sgen.exe для генерации XmlSerializationWriter и XmlSerializationReader, которые генерируются при создании XmlSerializer. Затем вы изменяете вывод из sgen.exe. Не смешно. Совсем не весело. Но возможно.

...