here's my problem to be solved: I've a plugin-structure for multimedia shows that allows to implement media types in external assemblies by subclassing from a base class in my framework. A show holds a list of media types. Shows are loaded and saved in XML using the XmlSerializer. This all works, even with programatic type mapping for plugin MediaTypes.
However, I want to be able to load XML files that contain MediaTypes that are not known, because the plugin isn't available.
For illustration, here is such an XML file:
<MultiMediaShow>
<MediaTypes>
<SomeType />
<SomeType />
<AnotherType />
<UnknownTypeFromPluginNotLoaded />
</MediaTypes>
</MultiMediaShow>
In the above example, I assume 2 "known" MediaTypes SomeType and AnotherType, comming from 2 plugin assemblies. The third type (UnknownTypeFromPluginNotLoaded) is unknown.
I'm already able to deserialize such unknown objects, but struggle with the serialization. In my aplication, I've the following code so far:
// To be implemented / subclassed by plugin assembly types
public abstract class MediaType
{
}
public class UnknownMediaType : MediaType
{
[XmlAnyElement]
public XmlElement[] UnknownChildElements;
[XmlAnyAttribute]
public XmlAttibute[] UnknownAttributes;
[XmlIgnore]
public string XmlTagName; // stores the xml element tag name in the original document
}
[XmlRoot("MultimediaShow")]
public class MultimediaShow
{
public List<MediaType> MediaTypes = new List<MediaType>();
}
When deserializing this with XmlSerializer, I use the event UnknownElement and manually insert an UnknownMediaType element into show.MediaTypes:
void HandleUnknownElements(Show show, List<XmlElementEventArgs> unknownElementEvents, XmlAttributeOverrides overrides)
{
// add a root attribute to UnknownMediaType
XmlAttributes attrs = new XmlAttributes();
XmlRootAttribute xmlRoot = new XmlRootAttribute(e.Element.Name);
attrs.XmlRoot = xmlRoot;
XmlAttributeOverrides o = new XmlAttributeOverrides();
o.Add(typeof(UnknownMediaObject), attrs);
// use a new XmlSerializer and a memory stream for deserializting the object as UnknownMediaType.
XmlSerializer xmlSerializer = new XmlSerializer(typeof(UnknownMediaType), o);
using (MemoryStream memoryStream = new MemoryStream())
{
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.ImportNode(e.Element, true));
doc.Save(memoryStream);
memoryStream.Position = 0;
try
{
// deserialize the object, store the XML element name and insert it into the chapter
UnknownMediaType t = xmlSerializer.Deserialize(memoryStream) as UnknownMediaObject;
t.XmlTagName = e.Element.Name;
show.MediaTypes.Add(t);
}
catch (Exception exc)
{
System.Diagnostics.Debug.WriteLine(exc.ToString());
//return objectType.IsByRef ? null : Activator.CreateInstance(objectType);
}
}
}
The BIG BIG problem is that such an event doesn't seem to be available when serializing an object. What I get as output (not very surpising) is:
<MultiMediaShow>
<MediaTypes>
<SomeType />
<SomeType />
<AnotherType />
<UnknownMediaType /> // !!!! was 'UnknownTypeFromPluginNotLoaded' !!!!
</MediaTypes>
</MultiMediaShow>
However, this is obviously not the same as what I've deserialized. So the question is, how would I best solve this problem?!?!
All help highly appreciated!!
Cheers, Felix
UPDATE
I was wondering if it is possible to generate classes programmatically that derive from UnknownMediaType and have the class name taken from the UnknownMediaType.XmlTagName. Or, alternativly, to have an attribute for specifying the XML tag name of a class??
Cheers, Felix