네임 스페이스에 의해 버전을 사용할 때 XML을 적절한 개체로 직렬화하는 가장 좋은 방법은 무엇입니까?
-
03-07-2019 - |
문제
내 질문은 다음과 같습니다.
네임 스페이스에 의해 버전이있는 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; }
}
}
해결책
두 가지 제안 :
첫째, 아마도 그렇게하지 않을 수도 있습니다. 직렬화하는 경우 발신자가 스키마를 지정하지 않는 한 다른 방법보다 하나의 방법을 선호하십시오.
둘째, 발견을 위해 XML을 구문 분석하지 마십시오. 파일의 첫 100 바이트 (또는 정보를 얻으려면 멀리있는) 내에서 "Employee.v2"및 "Employee.v1"에서 문자열 일치 만 수행하십시오. 데이터 내에서 일반적인 문자열이되지 않는 한 작동해야합니다.
제휴하지 않습니다 StackOverflow