Aleksei,
Are you instantiating the XmlSerializer in CL1 or CL2?
If you are instantiating in CL1, then there is indeed no way to make
this work without rebuilding. Otherwise you could pass the Type
DoubleItem to the constructor of the XmlSerializer:
XmlSerializer xser = new XmlSerializer (typeof (DataRecord), new Type[]
{typeof(DoubleItem)});
However, this will probably not produce the XML format you're looking
for:
<?xml version="1.0" encoding="IBM437"?>
<DataRecord xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w
3.org/2001/XMLSchema-instance">
<DataItem Name="DI-1" />
<IntItem Name="II-1" IntValue="3" />
<DataItem xsi:type="DoubleItem" Name="DblI-1"
DoubleValue="3.1415926535897931"
/>
</DataRecord>
The DoubleItem is serialized as a <DataItem> element.
If you need to customize the format, then you can override the
serialization attributes on the Data property in the DataRecord class.
The code goes like this:
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes dataAttributes = new XmlAttributes();
dataAttributes.XmlElements.Add( new XmlElementAttribute( "DoubleItem",
typeof(DoubleItem) ) );
dataAttributes.XmlElements.Add( new XmlElementAttribute( "DataItem",
typeof(DataItem) ) );
dataAttributes.XmlElements.Add( new XmlElementAttribute( "IntItem",
typeof(IntItem) ) );
overrides.Add( typeof( DataRecord ), "Data", dataAttributes );
XmlSerializer xser = new XmlSerializer (typeof (DataRecord), overrides,
new Type[0], null, "" );
xser.Serialize (Console.Out, rec);
and you get the format you were looking for:
<?xml version="1.0" encoding="IBM437"?>
<DataRecord xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w
3.org/2001/XMLSchema-instance">
<DataItem Name="DI-1" />
<IntItem Name="II-1" IntValue="3" />
<DoubleItem Name="DblI-1" DoubleValue="3.1415926535897931" />
</DataRecord>
Notice here the attributes in the XmlAttributeOverrides collection
override all attributes in the original class. They are not added, to
the existing ones. You have to add the attributes for the DataItem and
IntItem types again, too.
HTH,
Christoph Schittko
MS MVP XML
http://weblogs.asp.net/cschittko -----Original Message-----
From: Aleksei Guzev [mailto:al***********@bigfoot.com]
Posted At: Thursday, November 25, 2004 4:13 AM
Posted To: microsoft.public.dotnet.xml
Conversation: Serializing instances of derived classes
Subject: Serializing instances of derived classes
Imagine one writing a class library CL1 for data storage.
He defines classes 'DataItem' and 'DataRecord' so that the latter
contains a collection of the former.
And he derives class 'IntItem' from 'DataItem'
[XmlRoot ("DataItem")]
[XmlInclude (typeof (IntItem))]
public class DataItem
{
public DataItem() {}
public DataItem (string name)
{
_name = name;
}
private string _name;
[XmlAttribute]
public string Name
{
get { return _name; }
set { _name = value; }
}
}
[XmlRoot ("IntItem")]
public class IntItem : SerializeDerivedClass.DataItem
{
public IntItem(){}
public IntItem (string name, int intValue) : base (name)
{
_intValue = intValue;
}
private int _intValue;
[XmlAttribute ("IntValue")]
public int IntValue
{
get { return _intValue; }
set { _intValue = value; }
}
}
[XmlRoot ("DataRecord")]
public class DataRecord
{
public DataRecord() {}
private DataItem [] _data;
[XmlElement ("DataItem", typeof (DataItem))]
[XmlElement ("IntItem", typeof (IntItem))]
public DataItem [] Data
{
get { return _data; }
set { _data = value; }
}
}
Now the following code works fine.
DataRecord rec = new DataRecord ();
rec.Data = new DataItem [3];
rec.Data [0] = new DataItem ("DI-1");
rec.Data [1] = new IntItem ("II-1", 3);
XmlSerializer xser = new XmlSerializer (typeof (DataRecord));
xser.Serialize (Console.Out, rec);
Its output is
<DataRecord>
<DataItem Name="DI-1" />
<IntItem Name="II-1" IntValue="3" />
</DataRecord>
Now another developer creates another class library CL2 containing
class 'DoubleItem'
derived from 'DataItem'. Of course, the second developer wishes the
code above
including the following line to work too
Rec.Data [2] = new DoubleItem ("DblI-1", Math.PI);
[XmlRoot ("DoubleItem")]
public class DoubleItem : SerializeDerivedClass.DataItem
{
public DoubleItem(){}
public DoubleItem (string name, double doubleValue) : base (name)
{
_doubleValue = doubleValue;
}
private double _doubleValue;
[XmlAttribute ("DoubleValue")]
public double DoubleValue
{
get { return _doubleValue; }
set { _doubleValue = value; }
}
}
This should produce
<DataRecord>
<DataItem Name="DI-1" />
<IntItem Name="II-1" IntValue="3" />
<DoubleItem Name="DblI-1" DoubleValue="3.1415.."/>
</DataRecord>
Can this behavior be achieved without rebuilding the first class
library CL1?
Why 'DoubleItem' is "not expected" while every instance
of 'DoubleItem' is 'DataItem'?
Aleksei Guzev