我必须XML(de)序列化以下类:
这给出了以下输出:
<ArrayOfPropertyFilter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PropertyFilter>
<AndOr>And</AndOr>
<LeftBracket>None</LeftBracket>
<Property>17</Property>
<Operator>Equal</Operator>
<Value xsi:type="xsd:string">lll</Value>
<RightBracket>None</RightBracket>
</PropertyFilter>
</ArrayOfPropertyFilter>
并且,在反序列化之后它给出了
如何“告诉”Serializer保持Value“按原样”,没有任何XML节点....(在具体情况下,Value应该是“lll”而不是包含Text“lll”的XMLNode)?
Bellow是C#中的完整工作示例。输出是
Value is ='System.Xml.XmlNode []'
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
namespace WindowsFormsApplication13
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
PropertyFilter filter = new PropertyFilter();
filter.AndOr = "Jora";
filter.Value = "haha";
filter.Property = 15;
var xml = filter.SerializeToString();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
PropertyFilter cloneFilter = xmlDoc.Deserialize<PropertyFilter>();
Console.WriteLine("Value is = '{0}'", cloneFilter.Value);
}
}
public class PropertyFilter
{
public string AndOr { get; set; }
public string LeftBracket { get; set; }
public int Property { get; set; }
public string Operator { get; set; }
public object Value { get; set; }
public string RightBracket { get; set; }
}
public static class Utils
{
public static string SerializeToString(this object instance)
{
if (instance == null)
throw new ArgumentNullException("instance");
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
XmlSerializer serializer = new XmlSerializer(
instance.GetType(), null, new Type[0], null, null);
serializer.Serialize(sw, instance);
return sb.ToString();
}
public static T Deserialize<T>(this XmlDocument xmlDoc)
{
XmlNodeReader reader = new XmlNodeReader(xmlDoc.DocumentElement);
XmlSerializer serializer = new XmlSerializer(typeof(T));
object obj = serializer.Deserialize(reader);
T myT = (T)obj;
return myT;
}
}
}
强调Anton的答案,第二个例子(用Groo的评论更新):
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
namespace WindowsFormsApplication13
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
PropertyFilter filter = new PropertyFilter();
filter.AndOr = "Jora";
var obj = new Hehe();
obj.Behehe = 4526;
filter.Value = obj;
filter.Property = 15;
var xml = filter.SerializeToString();
PropertyFilter cloneFilter = xml.Deserialize<PropertyFilter>();
Console.WriteLine("Value is = '{0}'", cloneFilter.Value);
}
}
public class Hehe
{
public int Behehe { get; set; }
public override string ToString()
{
return string.Format("behehe is '{0}'", Behehe);
}
}
public class PropertyFilter
{
public string AndOr { get; set; }
public string LeftBracket { get; set; }
public int Property { get; set; }
public string Operator { get; set; }
//[XmlElement(typeof(Hehe))]
public object Value { get; set; }
public string RightBracket { get; set; }
}
public static class Utils
{
public static string SerializeToString(this object instance)
{
if (instance == null)
throw new ArgumentNullException("instance");
StringBuilder sb = new StringBuilder();
XmlSerializer serializer = new XmlSerializer(instance.GetType(), null, new Type[0], null, null);
using (StringWriter sw = new StringWriter(sb))
{
serializer.Serialize(sw, instance);
}
return sb.ToString();
}
public static T Deserialize<T>(this string xmlString)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader sr = new StringReader(xmlString))
{
return (T)serializer.Deserialize(sr);
}
}
}
}
答案 0 :(得分:2)
好的,这是有道理的,你使用XmlDocument
进行反序列化。只需使用String
(或任何流阅读器,如@Seb already pointed out),它就可以使用:
public static class Utils
{
public static string SerializeToString(this object instance)
{
if (instance == null)
throw new ArgumentNullException("instance");
StringBuilder sb = new StringBuilder();
XmlSerializer serializer = new XmlSerializer(instance.GetType());
using (StringWriter sw = new StringWriter(sb))
{
serializer.Serialize(sw, instance);
}
return sb.ToString();
}
public static T Deserialize<T>(this string xmlString)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader sr = new StringReader(xmlString))
{
return (T)serializer.Deserialize(sr);
}
}
}
用法:
// serialize
var xml = filter.SerializeToString();
// deserialize
var cloneFilter = xml.Deserialize<PropertyFilter>();
<强> [编辑] 强>
另外,作为旁注:永远不要忘记处置实现IDisposable
的对象。这就是为任何实例化的using
添加Stream
构造的原因。
<强> [EDIT2] 强>
正如Anton所说,在这种情况下,您需要明确指定其他类型,因为XmlSerializer
不会搜索所有可能的类型来查找匹配的类。
稍微更好的解决方案可能是使用接受这些类型的XmlSerializer
重载(这样您就不需要手动添加属性):
public static T Deserialize<T>(this string xmlString)
{
Type[] typesToInclude = GetAllPossibleTypes();
XmlSerializer serializer = new XmlSerializer(typeof(T), typesToInclude);
using (StringReader sr = new StringReader(xmlString))
{
return (T)serializer.Deserialize(sr);
}
}
这可以在应用程序启动时完成一次,但是您需要提供适当的程序集(或多个程序集)以确保涵盖所有可能的类型:
public static class Utils
{
private static readonly Type[] _typesToInclude = GetPossibleUserTypes();
private static Type[] GetPossibleUserTypes()
{
// this part should be changed to load types from the assembly
// that contains your potential Value candidates
Assembly assembly = Assembly.GetAssembly(typeof(PropertyFilter));
// get public classes only
return assembly.GetTypes().Where(t => t.IsPublic && !t.IsAbstract).ToArray();
}
public static string SerializeToString(this object instance)
{
if (instance == null)
throw new ArgumentNullException("instance");
var sb = new StringBuilder();
var serializer = new XmlSerializer(instance.GetType(), _typesToInclude);
using (StringWriter sw = new StringWriter(sb))
{
serializer.Serialize(sw, instance);
}
return sb.ToString();
}
public static T Deserialize<T>(this string xmlString)
{
var serializer = new XmlSerializer(typeof(T), _typesToInclude);
using (StringReader sr = new StringReader(xmlString))
{
return (T)serializer.Deserialize(sr);
}
}
}
答案 1 :(得分:1)
只要Value
获取原始,XSD定义类型(如string
和int
)的值,或T
中某处提到的用户定义类型,Gree的解决方案就会有效的定义(T
本身,其属性的类型等)。一旦您需要反序列化与这些类型不同的类型的值,您必须声明所有可能类型的{ {1}} Value
,例如
XmlElementAttribute
答案 2 :(得分:0)
好的,试试这个,但我不确定你想要达到的目的。
public class PropertyFilter
{
public string AndOr {get; set;}
public string LeftBracket {get; set;}
public int Property {get; set;}
public string Operator {get; set;}
public object Value {get; set;}
public string RightBracket {get; set;}
}
public void MyMethod()
{
using (System.IO.StreamReader reader = new System.IO.StreamReader(@"Input.xml"))
{
System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer(typeof(PropertyFilter[]));
PropertyFilter[] deserialized = (PropertyFilter[])serializer.Deserialize(reader);
}
}
我只是将您的示例XML放在Input.xml
文件中。我希望这会有所帮助。