Was ist der beste Weg xml in geeignete Objekte serialisiert werden, wenn sie von Namespaces versioniert?

StackOverflow https://stackoverflow.com/questions/209502

Frage

Meine Frage ist folgende.

Ich habe xml, die von einem Namespace versioniert ist. Ich mag diese xml in das entsprechende Objekt serialisiert, aber der einzige Weg, ich weiß, dies zu tun bedeutet, dass ich die XML-zwei mal zu verarbeiten. Zuerst den Namensraum zu entdecken, und dann, um das Objekt des richtigen Typs auf dem entdeckt Namespace basiert serialisiert. Dies scheint fürchterlich ineffizient zu mir, und es muss eine Art und Weise unter Verwendung von Generika oder etwas sein, die geeignete Art von Objekt, um wieder ohne ‚wenn Namespace == x dann serialze zu diesem‘ zu überprüfen.

Im Folgenden finden Sie eine Probe des einzigen Weges, ich weiß, dies zu erreichen. Gibt es eine bessere oder effizientere Art und Weise?

Danke

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace TestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod3()
        {
            //Build up an employee object to xml
            Schema.v2.Employee employee = new Schema.v2.Employee { FirstName = "First", LastName = "Last" };
            string xml = employee.ObjectToXml<Schema.v2.Employee>();

            //Now pretend I don't know what type I am receiving.
            string nameSpace = GetNamespace(xml);
            Object newemp;
            if (nameSpace == "Employee.v2")
                newemp = XmlSerializationExtension.XmlToObject<Schema.v2.Employee>(null, xml);
            else
                newemp = XmlSerializationExtension.XmlToObject<Schema.v1.Employee>(null, xml);

            // Check to make sure that the type I got was what I made.
            Assert.AreEqual(typeof(Schema.v2.Employee), newemp.GetType());
        }

        public string GetNamespace(string s)
        {
            XDocument z = XDocument.Parse(s);
            var result = z.Root.Attributes().
                    Where(a => a.IsNamespaceDeclaration).
                    GroupBy(a => a.Name.Namespace == XNamespace.None ? String.Empty : a.Name.LocalName,
                            a => XNamespace.Get(a.Value)).
                    ToDictionary(g => g.Key,
                                 g => g.First());

            foreach (System.Xml.Linq.XNamespace item in result.Values)
                if (item.NamespaceName.Contains("Employee")) return item.NamespaceName;

            return String.Empty;
        }
    }

    public static class XmlSerializationExtension
    {
        public static string ObjectToXml<T>(this T Object)
        {
            XmlSerializer s = new XmlSerializer(Object.GetType());
            using (StringWriter writer = new StringWriter())
            {
                s.Serialize(writer, Object);
                return writer.ToString();
            }
        }
        public static T XmlToObject<T>(this T Object, string xml)
        {
            XmlSerializer s = new XmlSerializer(typeof(T));
            using (StringReader reader = new StringReader(xml))
            {
                object obj = s.Deserialize(reader);
                return (T)obj;
            }
        }
    } 
}

namespace Schema.v1
{
    [XmlRoot(ElementName = "Employee", Namespace= "Employee.v1", IsNullable = false)]
    public class Employee
    {
        [XmlElement(ElementName = "FirstName")]
        public string FirstName { get; set; }
        [XmlElement(ElementName = "LastName")]
        public string LastName { get; set; }
    }
}
namespace Schema.v2
{
    [XmlRoot(ElementName = "Employee", Namespace = "Employee.v2", IsNullable = false)]
    public class Employee
    {
        [XmlAttribute(AttributeName = "FirstName")]
        public string FirstName { get; set; }
        [XmlAttribute(AttributeName = "LastName")]
        public string LastName { get; set; }
    }
}
War es hilfreich?

Lösung

Zwei Vorschläge:

Zuerst vielleicht nicht tun, auf das alles. Wenn Sie die Serialisierung, bevorzugt ein Verfahren über die anderen, wenn der Anrufer ein Schema gibt.

Zweitens, analysiert nicht die XML für die Entdeckung; nur tun String-Matching auf „Employee.v2“ und „Employee.v1“ innerhalb von (sagen wir) die ersten 100 Bytes der Datei (oder aber weit müssen Sie die Informationen erhalten gehen). Das sollte funktionieren, es sei denn, diejenigen gemeinsame Strings innerhalb Ihrer Daten sein werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top