c# - How to implement ReadXml for SomeClass : IList<IFoo> where all instances of IFoo are IFoo<T> of varying T -
i have class need serialize/deserialize, , i'm half way there - have serialization functional, resulting in below xml. however, since i'm implementing ixmlserializable
myself, i'm uncertain implementation of readxml
should like, given somegenericclass<t>
serialized using attribute-based flagging rather explicit implementation if ixmlserializable
<?xml version="1.0" encoding="utf-16"?> <foocontainer fooname="dosomething"> <somegenericclassofstring xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema" value="foobar" name="firstparam" description="first paramater serialized" /> <somegenericclassofint32 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema" value="10000" name="nextparam" description="second serialized parameter" /> </foocontainer>
which want serialize instance of:
public class foocontainer : ilist<isomegenericclassbase>, ixmlserializable { public string fooname {get;set;} void ixmlserializable.writexml(xmlwriter writer) { var serializer = xmlserializer.fromtypes(new type[]{somegenericbaseclass})[0]; .select(item=>somegenericclassbase.converttome(item)) .tolist() .foreach(item=>serializer.serialize(writer, item)); } // ilist implementation omitted - wraps private list<isomegenericclassbase> }
where list contain instances along these lines:
public interface isomegenericclassbase { } public interface isomegenericbaseclass<t> : isomegenericbaseclass { } public class somegenericclassbase : isomegenericclassbase { public static somegenericclassbase converttome(isomegenericclassbase target) { return new somegenericclassbase() {property1 = target.property1; property2 = target.property2} } public static isomegenericbaseclass expanttotyped(somegenericclassbase target) { // implementation omitted - converts base class instance generic instance working out generic type saved data , reconstructing } } public class somegenericclass<t> : somegenericclassbase, isomegenericbaseclass<t> { [xmlattribute] public string name {get;set;} [xmlattribute] public string description{get;set;} [xmlattribute] public t value {get;set;} [xmlelement("")] public t[] validoptions {get;set;} }
edit: expanded implementation - realised was, didn't illustrate problem correctly
core issue want able serialize items implement interface, if somegenericclassbase
instances. per approach used in expandtotyped
method, i'm expecting consumers of class save sufficient data in their implementations allow resulting classes converted original form required. yes, there's loss of fidelity, it's 1 can live in exchange flexibility of using list of interfaces instead of list of base classes.
one solution sidestep issue (ixmlserializable.readxml looks quite painful anyway, e.g. collections). did scrap ixmlserializable, , instead generate class along lines of below.
please note whilst approach works, it's quite error prone if serializable instance used other serialization - synchronization maintained when serializationtarget
set or retrieved. when it's set, convert existing parameters appropriate instances , add them serializable list. when it's retrieved, if it's null, inflate whatever in current value.
however, if foocontainer changes after creation of object, won't maintain synchronization , gets serialized out of date. largely because i'm lazy , don't want implement ilist<somegenericclassbase>
again override add
, remove
methods (though more robust approach).
public class foocontainerserializable { public foocontainerserializable() {} public foocontainerserializable(foocontainer serializationtarget) { this.serializationtarget = serializationtarget; } [xmlignore] public foocontainer serializationtarget { { if (_serializationtarget == null) { _serializationtarget = new foocontainer(); // copy across extant collection properties here this.parameters.foreach(item=>_serializationtarget.add(item)); } return _serializationtarget; } set { // synchronize entity's entries here _serializationtarget = value; _serializationtarget.foreach(item=>this.parameters.add(item.deflate())); } } private foocontainer _serializationtarget; [xmlelement] public string fooname { {return this.serializationtarget.fooname;} set {this.serializationtarget.fooname = value;} } [xmlelement] public list<somegenericclassbase> parameters { {return _parameters ?? (_parameters = new list<somegenericclassbase>());} set {_parameters = value;} } }
Comments
Post a Comment