我有以下方法来保存一个对象到一个文件:

// Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
    XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
    TextWriter textWriter = new StreamWriter(filename);

    xmlSerializer.Serialize(textWriter, toSerialize);
    textWriter.Close();
}

我承认这不是我写的(我只是把它转换成一个接受类型参数的扩展方法)。

现在我需要它把xml作为字符串返回给我(而不是保存到文件中)。我正在调查这件事,但我还没有弄清楚。

我想对于熟悉这些物体的人来说,这可能很简单。如果没有,我最终会弄清楚的。


当前回答

我的2 p…

        string Serialise<T>(T serialisableObject)
        {
            var xmlSerializer = new XmlSerializer(serialisableObject.GetType());

            using (var ms = new MemoryStream())
            {
                using (var xw = XmlWriter.Create(ms, 
                    new XmlWriterSettings()
                        {
                            Encoding = new UTF8Encoding(false),
                            Indent = true,
                            NewLineOnAttributes = true,
                        }))
                {
                    xmlSerializer.Serialize(xw,serialisableObject);
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
            }
        }

其他回答

使用StringWriter而不是StreamWriter:

public static string SerializeObject<T>(this T toSerialize)
{
    XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());

    using(StringWriter textWriter = new StringWriter())
    {
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }
}

Note, it is important to use toSerialize.GetType() instead of typeof(T) in XmlSerializer constructor: if you use the first one the code covers all possible subclasses of T (which are valid for the method), while using the latter one will fail when passing a type derived from T.    Here is a link with some example code that motivate this statement, with XmlSerializer throwing an Exception when typeof(T) is used, because you pass an instance of a derived type to a method that calls SerializeObject that is defined in the derived type's base class: http://ideone.com/1Z5J1.

此外,Ideone使用Mono来执行代码;使用Microsoft . net运行时得到的实际异常与Ideone上显示的异常有不同的消息,但它同样失败。

我无法使用xhafan建议的JSONConvert方法

在。net 4.5中,即使添加了“System.Web.”扩展程序集引用我仍然无法访问JSONConvert。

然而,一旦你添加了引用,你可以使用以下方法打印出相同的字符串:

JavaScriptSerializer js = new JavaScriptSerializer();
string jsonstring = js.Serialize(yourClassObject);

序列化和反序列化XML/JSON (SerializationHelper.cs):

using Newtonsoft.Json;
using System.IO;
using System.Xml.Serialization;

namespace MyProject.Helpers
{
    public static class SerializationHelper
    {
        public static T DeserializeXml<T>(this string toDeserialize)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
            using (StringReader textReader = new StringReader(toDeserialize))
            {
                return (T)xmlSerializer.Deserialize(textReader);
            }
        }

        public static string SerializeXml<T>(this T toSerialize)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
            using (StringWriter textWriter = new StringWriter())
            {
                xmlSerializer.Serialize(textWriter, toSerialize);
                return textWriter.ToString();
            }
        }

        public static T DeserializeJson<T>(this string toDeserialize)
        {
            return JsonConvert.DeserializeObject<T>(toDeserialize);
        }

        public static string SerializeJson<T>(this T toSerialize)
        {
            return JsonConvert.SerializeObject(toSerialize);
        }
    }
}

在极少数情况下,您可能希望实现自己的String序列化。

但这可能是个坏主意,除非你知道自己在做什么。(例如用批处理文件序列化I/O)

类似这样的方法就可以达到目的(而且手动/批处理编辑也很容易),但是要注意应该做更多的检查,比如名称不包含换行符。

public string name {get;set;}
public int age {get;set;}

Person(string serializedPerson) 
{
    string[] tmpArray = serializedPerson.Split('\n');
    if(tmpArray.Length>2 && tmpArray[0].Equals("#")){
        this.name=tmpArray[1];
        this.age=int.TryParse(tmpArray[2]);
    }else{
        throw new ArgumentException("Not a valid serialization of a person");
    }
}

public string SerializeToString()
{
    return "#\n" +
           name + "\n" + 
           age;
}

代码安全说明

关于接受的答案,在XmlSerializer构造函数中使用toSerialize.GetType()而不是typeof(T)是很重要的:如果使用第一种方法,代码将覆盖所有可能的场景,而使用后一种方法有时会失败。

下面是一些示例代码的链接,其中XmlSerializer在使用typeof(T)时抛出异常,因为您将派生类型的实例传递给调用SerializeObject<T>()的方法,该方法是在派生类型的基类中定义的:http://ideone.com/1Z5J1。注意,Ideone使用Mono来执行代码:使用Microsoft . net运行时获得的实际异常有一个与Ideone上显示的不同的消息,但它同样失败。

为了完整起见,我在这里发布了完整的代码示例,以供将来参考,以防Ideone(我发布代码的地方)将来不可用:

using System;
using System.Xml.Serialization;
using System.IO;

public class Test
{
    public static void Main()
    {
        Sub subInstance = new Sub();
        Console.WriteLine(subInstance.TestMethod());
    }

    public class Super
    {
        public string TestMethod() {
            return this.SerializeObject();
        }
    }

    public class Sub : Super
    {
    }
}

public static class TestExt {
    public static string SerializeObject<T>(this T toSerialize)
    {
        Console.WriteLine(typeof(T).Name);             // PRINTS: "Super", the base/superclass -- Expected output is "Sub" instead
        Console.WriteLine(toSerialize.GetType().Name); // PRINTS: "Sub", the derived/subclass

        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        StringWriter textWriter = new StringWriter();

        // And now...this will throw and Exception!
        // Changing new XmlSerializer(typeof(T)) to new XmlSerializer(subInstance.GetType()); 
        // solves the problem
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }
}