泛型+ XML序列化+自定义对象

时间:2010-02-22 12:58:30

标签: c# generics serialization

我正在尝试泛型,我有这个(不那么)创建XMLSerializer类的好主意。拼凑在一起的代码如下:

public class Persist<T>
{
    private string _path;
    public Persist(string path) {
        this._path = path;
    }
    public void save(T objectToSave)
    {
        XmlSerializer s = new XmlSerializer(typeof(T));
        TextWriter w = new StreamWriter(this._path);
        try { s.Serialize(w, objectToSave); }
        catch (InvalidDataException e) { throw e; }
        w.Close(); w.Dispose();
    }
    public T load()
    {
        XmlSerializer s = new XmlSerializer(typeof(T));
        TextReader r = new StreamReader(this._path);
        T obj;
        try { obj = (T)s.Deserialize(r); }
        catch (InvalidDataException e) { throw e; }
        r.Close(); r.Dispose();
        return obj;
    }
}

问题在于:它在Persist<List<string>>Persist<List<int>>上正常工作,但在Persist<List<userObject>>或任何其他自定义(但可序列化)对象上无效。 userObject本身只是一个包含两个{get; set;}属性的类,我之前已将其序列化。

我不确定我的Persist类(泛型),XML序列化代码或其他地方是否存在问题:(非常感谢帮助〜

编辑:

userObject的代码

public class userObject
{
    public userObject(string id, string name)
    {
        this.id = id;
        this.name = name;
    }
    public string id { get;private set; }
    public string name { get;set; }
}

2 个答案:

答案 0 :(得分:2)

在我看来,您的代码应该正常工作 - 即使它确实存在一些缺陷。

编辑: 您的userObject课程不可序列化。 Xml序列化仅适用于具有公共无参数构造函数的类型 - 当前类不起作用。此外,您应该真的重写您的代码,以避免显式调用.Close().Dispose(),而是在可能的情况下更喜欢using - 因为您可能会获得随机文件如果在序列化期间的任何时候锁定,则会发生错误,并且您的方法会因异常而终止 - 因此不会调用.Dispose()

就个人而言,我倾向于使用just-for-serialization对象层次结构,它只是存储在xml中的数据的容器,并且避免任何行为 - 特别是副作用。然后你可以使用一个简单的小基类来实现这一点。

我在项目中使用的内容如下:

public class XmlSerializableBase<T> where T : XmlSerializableBase<T>
{
    static XmlSerializer serializer = new XmlSerializer(typeof(T));
    public static T Deserialize(XmlReader from) { return (T)serializer.Deserialize(from); }
    public void SerializeTo(Stream s) { serializer.Serialize(s, this); }
    public void SerializeTo(TextWriter w) { serializer.Serialize(w, this); }
    public void SerializeTo(XmlWriter xw) { serializer.Serialize(xw, this); }
}

...将序列化程序缓存在静态对象中,并简化了使用(在调用位置不需要通用的类型参数。

使用它的真实课程:

public class ArtistTopTracks {
    public string name;
    public string mbid;//always empty
    public long reach;
    public string url;
}

[XmlRoot("mostknowntracks")]
public class ApiArtistTopTracks : XmlSerializableBase<ApiArtistTopTracks> {
        [XmlAttribute]
        public string artist;
        [XmlElement("track")]
        public ArtistTopTracks[] track;
}

示例序列化调用:

using (var xmlReader = XmlReader.Create([...])) 
    return ApiArtistTopTracks.Deserialize(xmlReader);
//[...]

ApiArtistTopTracks toptracks = [...];
toptracks.SerializeTo(Console.Out);

答案 1 :(得分:1)

您的代码失败的原因可能有很多:在遇到问题时,此文本特别有用:Troubleshooting Common Problems with the XmlSerializer。也许你的用户对象中有一些类型层次结构,并且序列化程序不知道它?