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

当按名称空间进行版本控制时,将xml序列化为适当对象的最佳方法是什么?

  •  1
  • degnome  · 技术社区  · 17 年前

    我有一个由名称空间控制的xml。我想将接收到的xml序列化为适当的对象,但我知道的唯一方法是必须对xml进行两次处理。首先发现名称空间,然后根据发现的名称空间序列化为适当类型的对象。对我来说,这似乎是非常低效的,必须有某种方法使用泛型或其他东西来获取适当类型的对象,而不需要“if namespace==x然后序列化到该”检查。

    下面是我知道的实现这一点的唯一方法的示例。有更好或更有效的方法吗?

    谢谢

    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; }
        }
    }
    
    1 回复  |  直到 17 年前
        1
  •  1
  •   TheSmurf    17 年前

    两项建议:

    首先,也许根本不要这样做。如果要序列化,请选择一种方法而不是另一种方法,除非调用方指定模式。