开发者

Generics + XML Serialization + Custom Objects

I'm trying out Generics and I had this (not so) great idea of creating an XMLSerializer class. The code I pieced together is below:

public class Persist<T>
{
    private strin开发者_StackOverflow中文版g _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;
    }
}

Here's the problem: It works fine on Persist<List<string>> or Persist<List<int>> but not on Persist<List<userObject>> or any other custom (but serializable) objects. userObject itself is just a class with two {get;set;} properties, which I have serialized before.

I'm not sure if the problems on my Persist class (generics), XML Serialization code, or somewhere else :( Help is very much appreciated~

Edit:

code for 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; }
}


Looks to me like your code should just work - even though it does have a few flaws.

EDIT: Your userObject class isn't serializable. Xml serialization only works on types with a public, parameterless constructor - the current class won't work. Also, you should really rewrite your code to avoid explicit calls to .Close() or .Dispose() and instead prefer using where possible - as is, you might get random file locking if at any point during serialization an error occurs and your method terminates by exception - and thus doesn't call .Dispose().

Personally, I tend to use a just-for-serialization object hierarchy that's just a container for data stored in xml and avoids any behavior - particularly side effects. Then you can use a handly little base class that makes this simple.

What I use in my projects is the following:

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); }
}

...which caches the serializer in a static object, and simplifies usage (no generic type-paramenters needed at call-locations.

Real-life classes using it:

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;
}

Sample serialization calls:

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

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


There can be a number of reasons why your code fails: This text is particularly helpful when having issues: Troubleshooting Common Problems with the XmlSerializer . Maybe you have some type hierarchy in your user objects and the serializer does not know about it?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜