Reputation: 12532
How do I serialize a 'Type'?
I want to serialize to XML an object that has a property that is a type of an object. The idea is that when it is deserialized I can create an object of that type.
public class NewObject
{
}
[XmlRoot]
public class XmlData
{
private Type t;
public Type T
{
get { return t; }
set { t = value; }
}
}
static void Main(string[] args)
{
XmlData data = new XmlData();
data.T = typeof(NewObject);
try
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlData));
try
{
using (FileStream fs = new FileStream("test.xml", FileMode.Create))
{
serializer.Serialize(fs, data);
}
}
catch (Exception ex)
{
}
}
catch (Exception ex)
{
}
}
I get this exception: "The type ConsoleApplication1.NewObject was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."
Where do I put the [XmlInclude]? Is this even possible?
Upvotes: 12
Views: 24664
Reputation: 7054
XML serialization serializes only the public fields and property values of an object into an XML stream. XML serialization does not include type information. For example, if you have a Book object that exists in the Library namespace, there is no guarantee that it will be deserialized into an object of the same type.
Source: Details of XML serialization | Microsoft Docs
Upvotes: 3
Reputation: 4566
Type
class cannot be serialized because System.RuntimeType
is not accessible to our code, it is an internal CLR type. You may work around this by using the type's name instead, like this:
public class c
{
[XmlIgnore]
private Type t;
[XmlIgnore]
public Type T {
get { return t; }
set {
t = value;
tName = value.AssemblyQualifiedName;
}
}
public string tName{
get { return t.AssemblyQualifiedName; }
set { t = Type.GetType(value);}
}
}
Upvotes: 20
Reputation: 11
Ugly but it works. Make a Class which includes the object type and the serialized string.
ex
Class dummie
{
Type objType;
string xml;
}
Upvotes: 1
Reputation: 17793
The problem is that the type of XmlData.T is actually "System.RuntimeType" (a subclass of Type), which unfortunately is not public. This means there is no way of telling the serialise what types to expect. I suggest only serializing the name of the type, or fully qualified name as Jay Bazuzi suggests.
Upvotes: 1
Reputation: 12532
I ended up converting the Type name to a string to save it to XML.
When deserializing, I load all the DLLs and save the name of the type and type in a dictionary. When I load the XML with the Type Name, I can look up the name in the dictionary key and know the type based on the dictionary value.
Upvotes: 3
Reputation: 5947
You could potentially implement the IXmlSerializable
interface and use Type.FullName
(you may also need Type.AssemblyQualifiedName
) for serialization and the Assembly.GetType(string)
for deserialization of your type element.
Upvotes: 3