First, is it possible to use XmlArrayItem to declare two data types, DT1 and
DT2 where DT2 is a derived class, in an ArrayList as the same ElementName?
The following throws a "System.InvalidOperationException" exception when
creating the serializer.
[XmlArrayItem (typeof(InternalDataObject), ElementName="Test"),
XmlArrayItem (typeof(ExtendedDataObject), ElementName="Test")]
public virtual ArrayList Test
{
get { return m_alTest; }
set { m_alTest = value; }
}
Second, is it possible to dynamically add more XmlArrayItem, with typeof
metadata, attribute to a specific ArrayList during runtime to allow for
accounting of unknown, until run-time, derived types to be stored in the
ArrayList? It does not look like this is possible, but perhaps someone has
a sneaky trick or two.
Thanks!
Bennie Haelen - 15 Jan 2004 23:09 GMT
Hi,
You need to use "XmlInclude" to include the types of your Internal- and
Extend Data Object.
Below is an example:
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Collections;
using System.Xml.Serialization;
namespace testserialize
{
[Serializable]
public class BaseClass
{
public BaseClass()
{
}
public int x = 5;
}
[Serializable]
public class DerivedClass : BaseClass
{
public DerivedClass()
{
}
public int y = 8;
}
public class Foo
{
public int Bar = 10;
}
/// <summary>
/// Summary description for Class1.
/// </summary>
[Serializable]
[XmlInclude(typeof(DerivedClass)), XmlInclude(typeof(BaseClass))]
public class Class1
{
static void Main(string[] args)
{
XmlTextWriter writer = null;
Class1 test = new Class1();
try
{
if (!File.Exists("test.xml"))
{
File.Create("test.xml");
}
writer = new XmlTextWriter("test.xml", Encoding.Unicode);
writer.Formatting = Formatting.Indented;
XmlSerializer serializer = new XmlSerializer(typeof(Class1));
serializer.Serialize(writer, test);
}
catch(Exception caught)
{
Console.WriteLine(caught.ToString());
}
finally
{
writer.Close();
}
}
public Class1()
{
myArray = new ArrayList();
myArray.Add(new BaseClass());
myArray.Add(new DerivedClass());
}
[XmlArrayItem(typeof(DerivedClass), ElementName="Derived")]
[XmlArrayItem(typeof(BaseClass), ElementName="Base")]
public ArrayList myArray;
}
}
> First, is it possible to use XmlArrayItem to declare two data types, DT1 and
> DT2 where DT2 is a derived class, in an ArrayList as the same ElementName?
[quoted text clipped - 16 lines]
>
> Thanks!
Hollywood - 15 Jan 2004 23:46 GMT
Bennie,
Thanks, but that really doesn't answer the second portion of my query as it
assumes you know all the derived types that will be in a given list before
run-time begins. Thats a huge step backwards in terms of functionality for
arrays and collections.
> You need to use "XmlInclude" to include the types of your Internal- and
> Extend Data Object.
Hollywood - 16 Jan 2004 00:30 GMT
Even more frustrating is the following...
public class Test
{
...
public virtual ArrayList TestList
{
get { return m_alTest; }
set { m_alTest = value; }
}
...
}
[XmlInclude(typeof(B))]
public class A
{
...
}
public class B : A
{
...
public string MyValue2
{
get { return m_sMyValue; }
set { m_sMyValue = value;}
}
...
}
Serializing an instance of class Test that has one object, of type B, in
it's TestList gives you the following XML...
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TestList>
<anyType xsi:type="B">
<MyValue>1</MyValue>
</anyType>
</TestList>
</Test>
Of course, without the XmlInclude on class A it doesn't work. I should not
have to use the XmlInclude on class A to get the above XML, no excuses. The
serializer should assume since it has not been told of a class, that it
needs to write out the "xsi:type" attribute to define what class to
deserialize as.
Christoph Schittko [MVP] - 16 Jan 2004 05:23 GMT
1) No ... the XmlSerializer is pretty picky about only serializing XML that
it can deserialize as well. In your case the XmlSerializer cannot determine
which type it serialized, because you're assigning the same element name to
two different classes.
2) Yes, you can by passing an XmlAttributeOverrides object to the
XmlSerializer constructor. See [0] and [1] for more details.

Signature
HTH
Christoph Schittko [MVP, XmlInsider]
Software Architect, .NET Mentor
[0] http://www.topxml.com/xmlserializer/runtime_customization.asp
[1] http://www.topxml.com/xmlserializer/runtime_overrides.asp
> First, is it possible to use XmlArrayItem to declare two data types, DT1 and
> DT2 where DT2 is a derived class, in an ArrayList as the same ElementName?
[quoted text clipped - 16 lines]
>
> Thanks!
Hollywood - 16 Jan 2004 14:55 GMT
> 1) No ... the XmlSerializer is pretty picky about only serializing XML that
> it can deserialize as well. In your case the XmlSerializer cannot determine
> which type it serialized, because you're assigning the same element name to
> two different classes.
Mms, can't it use the "xsi:type" attribute like it does in other
situations? It seems that its hit or miss on what it can and can't do
depending on situations.
> 2) Yes, you can by passing an XmlAttributeOverrides object to the
> XmlSerializer constructor. See [0] and [1] for more details.
Thanks.. I'll take a look at those, probably missed those in my general
google search!