使用泛型 C# 反序列化动态 XML
Deserialize dynamic XML with generics C#
给出以下 XML:
<RESPONSE version="10">
<RESULTS MyAttribute="1" />
</RESPONSE>
我可以这样反序列化它:
[XmlRoot("RESPONSE")]
public class Response
{
[XmlElement(ElementName = "RESULTS")]
public Results Results {get;set;}
}
public class Results
{
[XmlAttribute(AttributeName = "MyAttribute")]
public bool MyAttribute { get; set; }
}
var serializer = new XmlSerializer(typeof(Response));
var result = (Response)serializer.Deserialize(new StringReader(xml));
这很好用。
然而,问题是我也想反序列化以下 XML 并且我不想复制响应 class,我想使用通用方法。
<RESPONSE version="10">
<SOCCER AnotherAttribute="1" />
</RESPONSE>
我已尝试执行以下操作:
[XmlRoot("Response")]
public class Response<T>
{
public T Data {get;set;}
}
public class SoccerRoot
{
[XmlElement(ElementName = "SOCCER")]
public class Soccer {get;set;}
}
public class Soccer
{
[XmlAttribute(AttributeName = "AnotherAttribute")]
public bool AnotherAttribute {get;set;}
}
var serializer = new XmlSerializer(typeof(Response<SoccerRoot>));
var result = (Response<SoccerRoot>)serializer.Deserialize(new StringReader(xml));
但这不起作用,我也尝试继承 Response class 但没有成功。
我收到以下错误:<xmlns='' > was not expected.
我的方法是否正确,或者在反序列化 XML 文件时是否无法使用通用方法?
尝试创建一个包含对象 RESULTS 和 SOCCER 的公共 class,然后根据数据,一个将为空,另一个将包含值。
class Program
{
static void Main(string[] args)
{
//
var xml = "<RESPONSE version=\"1\" ><SOCCER AnotherAttribute =\"1\" /></RESPONSE>";
var serializer = new XmlSerializer(typeof(Response<int>));
var result = (Response<int>)serializer.Deserialize(new StringReader(xml));
xml = "<RESPONSE version=\"10\"><RESULTS MyAttribute = \"1\" /></RESPONSE >";
result = (Response<int>)serializer.Deserialize(new StringReader(xml));
Console.ReadLine();
}
}
[XmlRoot("RESPONSE")]
public class Response<T>
{
[XmlAttribute(AttributeName = "version")]
public T Version { get; set; }
[XmlElement(ElementName = "SOCCER")]
public SoccerRoot SoccerRoot { get; set; }
[XmlElement(ElementName = "RESULTS")]
public Results Results { get; set; }
}
public class SoccerRoot
{
[XmlAttribute(AttributeName = "AnotherAttribute")]
public int AnotherAttribute { get; set; }
}
public class Results
{
[XmlAttribute(AttributeName = "MyAttribute")]
public bool MyAttribute { get; set; }
}
对于 Response<SoccerRoot>
,预期的 xml 布局将是:
<RESPONSE>
<Data>
<SOCCER AnotherAttribute=...>
与您所拥有的不匹配。无法自定义 T Data
的元素名称,只能使用属性 。
选项:
有多个根对象(SOCCER
、RESULTS
等各一个):
[XmlRoot("RESPONSE")]
public class SoccerRoot {
[XmlElement("SOCCER")]
public Soccer Soccer {get;set;}
}
[XmlRoot("RESPONSE")]
public class ResultsRoot {
[XmlElement("RESULTS")]
public Results Results {get;set;}
}
有一个根对象,它有多个 first-level 个子对象(一个用于 SOCCER
,一个用于 RESULTS
,等等 - 每个都属于一种类型
[XmlRoot("RESPONSE")]
public class Response {
[XmlElement("RESULTS")]
public Results Results {get;set;}
[XmlElement("SOCCER")]
public Soccer Soccer {get;set;}
}
使用泛型方法,但是失去了中间对象所以你有Response<Soccer>
(完全删除SoccerRoot
),并使用XmlAttributeOverrides
自定义元素名称,一定要缓存生成的XmlSerializer
(否则会以惊人的速度泄露)
坦率地说,我会选择前两个选项中的任何一个,而不要理会第三个选项。
给出以下 XML:
<RESPONSE version="10">
<RESULTS MyAttribute="1" />
</RESPONSE>
我可以这样反序列化它:
[XmlRoot("RESPONSE")]
public class Response
{
[XmlElement(ElementName = "RESULTS")]
public Results Results {get;set;}
}
public class Results
{
[XmlAttribute(AttributeName = "MyAttribute")]
public bool MyAttribute { get; set; }
}
var serializer = new XmlSerializer(typeof(Response));
var result = (Response)serializer.Deserialize(new StringReader(xml));
这很好用。 然而,问题是我也想反序列化以下 XML 并且我不想复制响应 class,我想使用通用方法。
<RESPONSE version="10">
<SOCCER AnotherAttribute="1" />
</RESPONSE>
我已尝试执行以下操作:
[XmlRoot("Response")]
public class Response<T>
{
public T Data {get;set;}
}
public class SoccerRoot
{
[XmlElement(ElementName = "SOCCER")]
public class Soccer {get;set;}
}
public class Soccer
{
[XmlAttribute(AttributeName = "AnotherAttribute")]
public bool AnotherAttribute {get;set;}
}
var serializer = new XmlSerializer(typeof(Response<SoccerRoot>));
var result = (Response<SoccerRoot>)serializer.Deserialize(new StringReader(xml));
但这不起作用,我也尝试继承 Response class 但没有成功。
我收到以下错误:<xmlns='' > was not expected.
我的方法是否正确,或者在反序列化 XML 文件时是否无法使用通用方法?
尝试创建一个包含对象 RESULTS 和 SOCCER 的公共 class,然后根据数据,一个将为空,另一个将包含值。
class Program
{
static void Main(string[] args)
{
//
var xml = "<RESPONSE version=\"1\" ><SOCCER AnotherAttribute =\"1\" /></RESPONSE>";
var serializer = new XmlSerializer(typeof(Response<int>));
var result = (Response<int>)serializer.Deserialize(new StringReader(xml));
xml = "<RESPONSE version=\"10\"><RESULTS MyAttribute = \"1\" /></RESPONSE >";
result = (Response<int>)serializer.Deserialize(new StringReader(xml));
Console.ReadLine();
}
}
[XmlRoot("RESPONSE")]
public class Response<T>
{
[XmlAttribute(AttributeName = "version")]
public T Version { get; set; }
[XmlElement(ElementName = "SOCCER")]
public SoccerRoot SoccerRoot { get; set; }
[XmlElement(ElementName = "RESULTS")]
public Results Results { get; set; }
}
public class SoccerRoot
{
[XmlAttribute(AttributeName = "AnotherAttribute")]
public int AnotherAttribute { get; set; }
}
public class Results
{
[XmlAttribute(AttributeName = "MyAttribute")]
public bool MyAttribute { get; set; }
}
对于 Response<SoccerRoot>
,预期的 xml 布局将是:
<RESPONSE>
<Data>
<SOCCER AnotherAttribute=...>
与您所拥有的不匹配。无法自定义 T Data
的元素名称,只能使用属性 。
选项:
有多个根对象(
SOCCER
、RESULTS
等各一个):[XmlRoot("RESPONSE")] public class SoccerRoot { [XmlElement("SOCCER")] public Soccer Soccer {get;set;} } [XmlRoot("RESPONSE")] public class ResultsRoot { [XmlElement("RESULTS")] public Results Results {get;set;} }
有一个根对象,它有多个 first-level 个子对象(一个用于
SOCCER
,一个用于RESULTS
,等等 - 每个都属于一种类型[XmlRoot("RESPONSE")] public class Response { [XmlElement("RESULTS")] public Results Results {get;set;} [XmlElement("SOCCER")] public Soccer Soccer {get;set;} }
使用泛型方法,但是失去了中间对象所以你有
Response<Soccer>
(完全删除SoccerRoot
),并使用XmlAttributeOverrides
自定义元素名称,一定要缓存生成的XmlSerializer
(否则会以惊人的速度泄露)
坦率地说,我会选择前两个选项中的任何一个,而不要理会第三个选项。