c# - XML serialization of interface property -
i xml serialize object has (among other) property of type imodelobject (which interface).
public class example { public imodelobject model { get; set; } }
when try serialize object of class, receive following error:
"cannot serialize member example.model of type example because interface."
i understand problem interface cannot serialized. however, concrete model object type unknown until runtime.
replacing imodelobject interface abstract or concrete type , use inheritance xmlinclude possible, seems ugly workaround.
any suggestions?
this inherent limitation of declarative serialization type information not embedded within output.
on trying convert <flibble foo="10" />
into
public class flibble { public object foo { get; set; } }
how serializer know whether should int, string, double (or else)...
to make work have several options if don't know till runtime easiest way using xmlattributeoverrides.
sadly work base classes, not interfaces. best can there ignore property isn't sufficient needs.
if must stay interfaces have 3 real options:
hide , deal in property
ugly, unpleasant boiler plate , repetition consumers of class not have deal problem:
[xmlignore()] public object foo { get; set; } [xmlelement("foo")] [editorvisibile(editorvisibility.advanced)] public string fooserialized { { /* code here convert type in foo string */ } set { /* code parse out serialized value , make foo instance of proper type*/ } }
this become maintenance nightmare...
implement ixmlserializable
similar first option in take full control of things but
- pros
- you don't have nasty 'fake' properties hanging around.
- you can interact directly xml structure adding flexibility/versioning
- cons
- you may end having re-implement wheel other properties on class
issues of duplication of effort similar first.
modify property use wrapping type
public sealed class xmlanything<t> : ixmlserializable { public xmlanything() {} public xmlanything(t t) { this.value = t;} public t value {get; set;} public void writexml (xmlwriter writer) { if (value == null) { writer.writeattributestring("type", "null"); return; } type type = this.value.gettype(); xmlserializer serializer = new xmlserializer(type); writer.writeattributestring("type", type.assemblyqualifiedname); serializer.serialize(writer, this.value); } public void readxml(xmlreader reader) { if(!reader.hasattributes) throw new formatexception("expected type attribute!"); string type = reader.getattribute("type"); reader.read(); // consume value if (type == "null") return;// leave t @ default value xmlserializer serializer = new xmlserializer(type.gettype(type)); this.value = (t)serializer.deserialize(reader); reader.readendelement(); } public xmlschema getschema() { return(null); } }
using involve (in project p):
public namespace p { public interface ifoo {} public class realfoo : ifoo { public int x; } public class otherfoo : ifoo { public double x; } public class flibble { public xmlanything<ifoo> foo; } public static void main(string[] args) { var x = new flibble(); x.foo = new xmlanything<ifoo>(new realfoo()); var s = new xmlserializer(typeof(flibble)); var sw = new stringwriter(); s.serialize(sw, x); console.writeline(sw); } }
which gives you:
<?xml version="1.0" encoding="utf-16"?> <mainclass xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema"> <foo type="p.realfoo, p, version=1.0.0.0, culture=neutral, publickeytoken=null"> <realfoo> <x>0</x> </realfoo> </foo> </mainclass>
this more cumbersome users of class though avoids boiler plate.
a happy medium may merging xmlanything idea 'backing' property of first technique. in way of grunt work done consumers of class suffer no impact beyond confusion introspection.
Comments
Post a Comment