c# - How to serialize IEnumerable<char> as string & Confusing Deserialization error -
lets have following simple class:
[xmlroot] [xmltype("string")] public partial class estring : ienumerable<char> { string asstring {get;set;} public ienumerator<char> getenumerator() { return this.asstring.tochararray().tolist().getenumerator(); } ienumerator ienumerable.getenumerator() { return this.asstring.tochararray().getenumerator(); } public void add(char character) { this.asstring += character; } }
also namedvalue class:
[xmlroot] public partial class enamedvalue: keyvaluepair<estring,object> {...}
and finally,
[xmlroot] public partial class elist<t>: list<enamedvalue> {...}
now, serialize elist or class inherits elist using following xml serializer:
public static xdocument serialize<t>(this t obj) t: new() { type tt = obj.gettype(); xmlserializer xssubmit = new xmlserializer(tt); stringwriter sww = new stringwriter(); xmlwriter writer = xmlwriter.create(sww); xssubmit.serialize(writer, obj); return xdocument.parse(sww.tostring()); }
serialization works - estring being serialized character array, instead of getting "string", individual characters values:
<enamedlist> <key>99</key> <key>111</key> <key>100</key> <key>101</key>...
also, on deserialization (solved, see update#1 below):
public static t deserialize<t>(this xdocument xml) t: new() { var serializer = new xmlserializer(typeof(t)); t result; using (textreader reader = new stringreader(xml.tostring())) { result = (t)serializer.deserialize(reader); } return result; }
i receive following error:
system.runtime.serialization.serializationexception: error in line 1 position 111. expecting element 'enamedlist' namespace 'http://schemas.datacontract.org/2004/07/epic'.. encountered 'element' name 'enamedlist', namespace ''.
so, questions become:
- how control serialization of
estring
, orienumerable<char>
, serialize string? - why, when element names match, failure on deserialization? (am missing namespace declaration?)
thanks!
update #1: so, removed ienumerable<char>
interface estring, , left ienumerable<char>.getenumerator()
method, allows string used ienumerable<char>
while in foreach loop, serializes string. #win
also, dbc, updated original post xml deserializer (rather datacontract serializer) , deserialization works.
to answer questions:
you shouldn't reinvent wheel custom string solutions. regardless, if want (insanely) high-level of control on (de-)serialization, implement ixmlserializable , exact same thing yourself.
[xmlroot("string-wrapper")] public class customstring : ixmlserializable { public string value { get; set; } public xmlschema getschema() { return null; // getschema should not used. } public void readxml(xmlreader reader) { reader.movetocontent(); bool isempty = reader.isemptyelement; reader.readstartelement(); if (!isempty) { value = reader.readstring(); reader.readendelement(); } } public void writexml(xmlwriter writer) { writer.writestring(value); } }
serialization of customstring yields <string-wrapper>testing</string-wrapper>
. i'll post test code @ end of post.
- your deserialization broken because xmlserializer doesn't know ienumerable marked serializable should treated string.
and now... forget told you. unless have specific formatting requirements should not implement own version of string. built-in formatter knows lot more formatting tricks (http://www.w3.org/tr/xmlschema-2/#built-in-datatypes), should let it's job.
serializing classes attributes come in, though recommend switch wfc data contracts, may sound scary @ first provides whole lot more lot less code. again, i'm not sure you're trying accomplish, trust me don't want habit of hand writing xml.
if you're might dynamic objects , expandoobject (http://www.codeproject.com/tips/227139/converting-xml-to-an-dynamic-object-using-expandoo). these eliminate types , allow create dictionaries, arrays, named properties, whatever, on fly!
finally, easy on generics! deserializing generic classes not trivial task. besides, don't need to. if want own collections, try system.collections.objectmodel namespace. don't have worry maintaining lists , implementing interfaces, you're storing:
class dictionaryofstringsandobjects : keyedcollection<string, object {...} class collectionofstrings : collection<string> {...}
also, try avoid partial classes unless orm or large legacy class forces on you. shouldn't use them unless you're made to.
all best, , future devoid of xml!
public class customserializer { public static void test() { var obj = new customstring {value = "random string!"}; var serializer = new customserializer(); var xml = serializer.serialize(obj); console.writeline(xml); var obj2 = serializer.deserialize<customstring>(xml); } public string serialize(object obj) { var serializer = new xmlserializer(obj.gettype()); using (var io = new stringwriter()) { serializer.serialize(io, obj); return io.tostring(); } } public t deserialize<t>(string xml) { var serializer = new xmlserializer(typeof (t)); using (var io = new stringreader(xml)) { return (t)serializer.deserialize(io); } } }
Comments
Post a Comment