I have written a sample to illustrate the error I am getting. If I am able to serialize, I should be able to deserialize as well.
But I get following exception when I run this sample.
The specified type was not recognized: name='Sample', namespace='AppConsole_ChandraSandpit', at SampleBase xmlns='AppConsole_ChandraSandpit'>
[XmlInclude(typeof(Sample))]
public class SampleBase
{
}
public class Sample : SampleBase
{
}
public class SampleGroup
{
public SampleBase Samples
{
get;
set;
}
public void populate()
{
Samples = new Sample();
}
/// <summary>
/// Hydrates the object to xml string.
/// </summary>
/// <returns>serialized xml string of this object</returns>
public String Hydrate()
{
String xmlString = String.Empty;
try
{
xmlString = XMLSerializationHelper.SerializeObjectToXml<SampleGroup>(this);
}
catch (InvalidOperationException HydrateException)
{
throw new InvalidOperationException(String.Format("Could not Hydrate {0} to xmlstring. Please see inner exception for details", this.GetType().ToString()), HydrateException.InnerException);
}
return xmlString;
}
/// <summary>
/// Dehydrates the xml string to object.
/// </summary>
/// <param name="xmltoDehydarte">xml string to be dehydrated to object</param>
/// <returns>deHydrated object</returns>
public SampleGroup Dehydrate(String xmltoDehydarte)
{
SampleGroup dehydratedObject = null;
if (!String.IsNullOrEmpty(xmltoDehydarte))
{
try
{
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "SampleGroup";
xRoot.Namespace = "AppConsole_ChandraSandpit";
xRoot.IsNullable = true;
dehydratedObject = XMLSerializationHelper.DeserializeXmlToObject<SampleGroup>(xmltoDehydarte, xRoot);
}
catch (InvalidOperationException deHydrateException)
{
throw new InvalidOperationException(String.Format("Could not deHydrate {0} to xmlstring. Please see inner exception for details", this.GetType().ToString()), deHydrateException.InnerException);
}
}
return dehydratedObject;
}
}
Following code for Serialization helper
public class XMLSerializationHelper : XmlSerializer
{
public static T DeserializeXmlToObject<T>(string xml, XmlRootAttribute xRoot)
{
using (MemoryStream memoryStream = new MemoryStream(StringToByteArrayUtf8(xml)))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), xRoot);
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
return (T)xmlSerializer.Deserialize(xmlTextWriter.BaseStream);
}
}
public static string SerializeObjectToXml<T>(T obj)
{
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), typeof(T).Namespace);
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xmlSerializer.Serialize(xmlTextWriter, obj);
memoryStream = (MemoryStream) xmlTextWriter.BaseStream;
string xmlString = ByteArrayToStringUtf8(memoryStream.ToArray());
xmlTextWriter.Close();
memoryStream.Close();
memoryStream.Dispose();
return xmlString;
}
}
Can use the following in a console to test
internal class Program
{
private static void Main(string[] args)
{
SampleGroup SG = new SampleGroup();
SG.populate();
SG = SG.Dehydrate(SG.Hydrate());
Console.WriteLine("Test Complete press a Key");
Console.ReadKey();
}
}
abandoning XmlSerializer and using the IXmlSerializable interface directly seems to be the only solution. xmlSerializer uses reflection and cant handle this simple situation. It basically does not know what to expect when its reflecting on the generic type and expecting a concerete type. Refer the answer here