Groups | Blog | Home
all groups > dotnet xml > january 2005 >

dotnet xml : InvalidCastException upon serializing IXmlSerializable class


mattoc NO[at]SPAM tiscali.co.uk
1/4/2005 8:10:23 AM
Happy new year to all.

I have a strange error that I've been trying for a while now to
fathom..

Basically I have a hierarchy of state classes that I need to serialize
to XML. Some of them can contain Exceptions, so I've decided to
implement IXmlSerializable to get round the fact that Exception is not
serializable.

Here's the implementation code from the (abstract) superclass:

#region IXmlSerializable Members

public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteAttributeString(XmlNamespaces.XmlSchemaInstance.Prefix,
"type", XmlNamespaces.XmlSchemaInstance.Uri.ToString(),
this.GetType().Name);
WriteAdditionalContentXml(writer);
}

public System.Xml.Schema.XmlSchema GetSchema()
{

XmlSchema schema = new XmlSchema();
schema.Id = this.GetType().FullName;
schema.TargetNamespace = XmlNamespaces.Service.Uri.ToString();

schema.Namespaces.Add(XmlNamespaces.Service.Prefix,
XmlNamespaces.Service.Uri.ToString());
schema.Namespaces.Add(XmlNamespaces.XmlSchemaInstance.Prefix,
XmlNamespaces.XmlSchemaInstance.Uri.ToString());

XmlSchemaComplexType state = new XmlSchemaComplexType();
state.Name = this.GetType().Name;
schema.Items.Add(state);

XmlSchemaSequence sequence = new XmlSchemaSequence();
sequence.MinOccurs = 0;
sequence.MaxOccurs = 1;

AddSchemaContent(schema, sequence);

if (sequence.Items.Count > 0)
{
state.Particle = sequence;
}

schema.Compile(new ValidationEventHandler(schemaValidationHandler));

return schema;
}

public virtual void ReadXml(System.Xml.XmlReader reader)
{
}

protected virtual void WriteAdditionalContentXml(XmlWriter writer)
{
}

protected virtual void AddSchemaContent(XmlSchema schema,
XmlSchemaSequence parentSequence)
{
}

private void schemaValidationHandler(object sender,
ValidationEventArgs args)
{
Trace.WriteLine(args.Message);
Debug.Fail(args.Message + ":" + Environment.NewLine +
Environment.NewLine + args.Exception.ToString() + Environment.NewLine +
Environment.NewLine);
}

#endregion

The problem is this. I can (de)serialize whichever type is specified as
the first argument in the XmlSerializer constructor. However, attempts
to serialize any types that are specified in the additional types
argument fail with an InvalidOperationException ("There was an error
generating the XML document"), the inner exception of which is an
InvalidCastException ("Specified cast is not valid"), and the stack
trace of which is:

at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter
xmlWriter, Object o, XmlSerializerNamespaces namespaces, String
encodingStyle)
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter
xmlWriter, Object o)
at
Limit.Company.LossAdjustment.Tests.State.StatesTest.serialize(FeeState
state, XmlSerializer serializer) in
q:\projects\limit\limit.company.lossadjustment.tests\state\statestest.cs:line
131
at
Limit.Company.LossAdjustment.Tests.State.StatesTest.XmlSerializeErrorState()
in
q:\projects\limit\limit.company.lossadjustment.tests\state\statestest.cs:line
71
--InvalidOperationException
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write1_State(Object
o)

Furthermore, if I explicitly create XML that matches the schema of one
of the additional types, it deserializes, but to the type that was
specified as the FIRST argument of the XmlSerializer constructor. I
guess this means that I have problems with my schemas somewhere, but
I'm at a loss as to how to fix them.

Many thanks in advance,

Matt
mattoc NO[at]SPAM tiscali.co.uk
1/10/2005 7:56:09 AM
okay - i have figured out what the problem is, and it is nothing to do
with the IXmlSerializable interface.

basically, I was trying to use the XmlSerializer in a manner whereby I
would specify that the object I was passing it was any of types A, B, C
or D. it can't handle this. you must specify the type you are passing
it to serialize and then only ever pass it this type. this main type
can contain the other types as part of an object graph, but that's as
far as it goes.

why does it need to know the type you're passing it anyway? surely that
it is marked serializable is enough..


[quoted text, click to view]
AddThis Social Bookmark Button