Search code examples
c#xmlxml-deserialization

Xml Deserialize to System.Type


I'm trying to deserialize a piece of XML that specifies a .NET type to an instance of System.Type. Given

<SomeObject>
  <SomeType>System.String, mscorlib</SomeType>
</SomeObject>

To deserialize to a class;

public class SomeObject
{
    public Type SomeType { get; set; }
}

Annoyingly, I've actually done this before a while back but without access to that source code and not being able to remember, this has proven very difficult to research the solution given the keywords needed ("Xml", "Deserialize", "Type" gives pretty much everything under the sun).

From what I remember, there is a simple Attribute that I put on the SomeType property and the XmlSerializer takes care of it from there. Does anyone know what attribute I need or am I mis-remembering?


Solution

  • If you don't want to have additional property of type string (usual solution to this problem) - you can use proxy class like this:

    public class XmlTypeProxy : IXmlSerializable {
        private string _typeName;
    
        public XmlTypeProxy() {
    
        }
    
        public XmlTypeProxy(string typeName) {
            _typeName = typeName;
        }
    
        public XmlSchema GetSchema() {
            return null;
        }
    
        public void ReadXml(XmlReader reader) {
            _typeName = reader.ReadString();
        }
    
        public void WriteXml(XmlWriter writer) {
            writer.WriteString(_typeName);
        }
    
        public static implicit operator Type(XmlTypeProxy self) {
            return Type.GetType(self._typeName);
        }
    
        public static implicit operator XmlTypeProxy(Type self) {
            return new XmlTypeProxy(self.AssemblyQualifiedName);
        }
    }
    

    What this class does is just stores type assembly qualified name as string and defines implicit conversion operator from and to Type type. Then you just need to decorate SomeType with XmlElement attribute and specify it's Type is XmlTypeProxy:

    public class SomeObject {
        [XmlElement(Type = typeof(XmlTypeProxy))]
        public Type SomeType { get; set; }
    }
    

    Now, because there is implicit converstion from Type to XmlTypeProxy (and visa versa) - both serialization and deserialization will work as you expect.