将对象序列化为XElement并在内存中反序列化它

Ari*_*ian 55 c# xml linq serialization c#-4.0

我想将一个对象序列化为XML,但我不想将它保存在磁盘上.我想将它保存在XElement变量中(用于LINQ),然后反序列化回我的对象​​.

我怎样才能做到这一点?

Abd*_*nim 98

您可以使用这两种扩展方法在XElement和对象之间进行序列化和反序列化.

public static XElement ToXElement<T>(this object obj)
{
    using (var memoryStream = new MemoryStream())
    {
        using (TextWriter streamWriter = new StreamWriter(memoryStream))
        {
            var xmlSerializer = new XmlSerializer(typeof(T));
            xmlSerializer.Serialize(streamWriter, obj);
            return XElement.Parse(Encoding.ASCII.GetString(memoryStream.ToArray()));
        }
    }
}

public static T FromXElement<T>(this XElement xElement)
{
        var xmlSerializer = new XmlSerializer(typeof(T));
        return (T)xmlSerializer.Deserialize(xElement.CreateReader());
}
Run Code Online (Sandbox Code Playgroud)

用法

XElement element = myClass.ToXElement<MyClass>();
var newMyClass = element.FromXElement<MyClass>();
Run Code Online (Sandbox Code Playgroud)

  • 你应该使用public static XElement ToXElement <T>(this T obj) (11认同)
  • 你应该使用`Encoding.UTF8`而不是`Encoding.ASCII`.否则,如果你有一个字符串属性,如"Наберегупустынныхволн",这将打破.或者您可以使用MemoryStream或Encoding显式旁路(请参阅我的回答). (7认同)
  • 创建扩展方法的好方法. (5认同)
  • 不是`StreamWriter`默认为`Encoding.UTF8`,**不是**`Encoding.ASCII`?参考:http://msdn.microsoft.com/en-us/library/wtbhzte9.aspx. (5认同)
  • 如果我们首先将对象写入字符串xml然后再写入XElement,那么这种方法的性能可能不是最优的? (3认同)
  • 不确定为什么这个解决方案如此投票.首先,指定编码用于解析,但不用于写入 - 这是一个错误,因为Encoding.Default可能不是ASCII.其次,它的效率低于@Surjit Samra的答案 - 你转换对象> XmlDocument> string> byte []> string> XDocument.他的解决方案确实对象> XmlDocument> XDocument convertion.第三,对System.Object进行扩展方法是一个非常糟糕的做法 - 它会在你的intellisense中添加如此多的垃圾! (3认同)
  • @CarlSixsmith你是对的 - 在这种情况下,在使用时不需要指定泛型类型.谢谢 (2认同)
  • 考虑使用T generic作为object参数而不是"object" (2认同)

Sur*_*mra 25

您可以使用XMLSerialization

XML序列化是将对象的公共属性和字段转换为串行格式(在本例中为XML)以进行存储或传输的过程.反序列化从XML输出重新创建其原始状态的对象.您可以将序列化视为将对象的状态保存到流或缓冲区中的一种方法.例如,ASP.NET使用XmlSerializer类对XML Web服务消息进行编码

XDocument Represents an XML document来实现这一目标

   using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;


namespace ConsoleApplication5
{
  public class Person
  {
    public int Age { get; set; }
    public string Name { get; set; }
  }

  class Program
  {
    static void Main(string[] args)
    {

      XmlSerializer xs = new XmlSerializer(typeof(Person));

      Person p = new Person();
      p.Age = 35;
      p.Name = "Arnold";

      Console.WriteLine("\n Before serializing...\n");
      Console.WriteLine(string.Format("Age = {0} Name = {1}", p.Age,p.Name));

      XDocument d = new XDocument();
      using (XmlWriter xw = d.CreateWriter())
        xs.Serialize(xw, p);

      // you can use LINQ on elm now

      XElement elm = d.Root;

      Console.WriteLine("\n From XElement...\n");

      elm.Elements().All(e => { Console.WriteLine(string.Format("element name {0} , element value {1}", e.Name, e.Value)); return true; });

      //deserialize back to object
      Person pDeserialized = xs.Deserialize((d.CreateReader())) as Person;

      Console.WriteLine("\n After deserializing...\n");
      Console.WriteLine(string.Format("Age = {0} Name = {1}", p.Age, p.Name));

      Console.ReadLine();

    }
  }


}
Run Code Online (Sandbox Code Playgroud)

这是输出 在此输入图像描述


Ere*_*mez 14

(迟到的答案)

连载:

var doc = new XDocument();
var xmlSerializer = new XmlSerializer(typeof(MyClass));
using (var writer = doc.CreateWriter())
{
    xmlSerializer.Serialize(writer, obj);
}
// now you can use `doc`(XDocument) or `doc.Root` (XElement)
Run Code Online (Sandbox Code Playgroud)

反序列化:

MyClass obj; 
using(var reader = doc.CreateReader())
{
    obj = (MyClass)xmlSerializer.Deserialize(reader);
}
Run Code Online (Sandbox Code Playgroud)