DiskJunky
DiskJunky

Reputation: 4971

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?

Upvotes: 2

Views: 382

Answers (2)

DiskJunky
DiskJunky

Reputation: 4971

While I've marked Evk's answer as correct (and it is if you are deserializing more than one Type property), I actually went with a simpler approach in the end.

Based on this answer, I modified by SomeObject to;

public class SomeObject
{
    public string SomeTypeName
    {
        get { return SomeType.AssemblyQualifiedName; }
        set
        {
            var converter = new TypeNameConverter();
            SomeType = (Type)converter.ConvertFrom(value);
        }
    }

    [XmlIgnore]
    public Type SomeType { get; set; }
}

While a shorter piece of code for a single property, it's not as robust as the accepted answer. I'm recording here has the two approaches may help others.

Upvotes: 0

Evk
Evk

Reputation: 101443

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.

Upvotes: 1

Related Questions