Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XmlSerializer constructor with XmlTypeMapping and XmlRootAttribute arguments

I'd like to prefetch in C#, the XmlTypeMapping of a known set of class types to speed up XML deserialization of them while instantiating a new XmlSerializer as XmlReflectionImporter.ImportTypeMapping (happening during XmlSerializer contruction on a class type) is quite time consuming and seem to happen at each XmlSerializer construction.

In addition the xml content I am parsing forces me to use XmlRootAttribute argument to set the xml root element name to parse as it is not always the same. To achieve that, I can use the XmlSerializer(Type, XmlRootAttribute) constructor to deserialize my object.

However I would also like to benefit from the prefetch XmlTypeMapping and I can't see any XmlSerializer constructor like : XmlSerializer( XmlTypeMapping, XmlRootAttribute ) or something close. How could I achieve that?

Any help would be greatly appreciated! Thanks.

like image 409
dletozeun Avatar asked Sep 29 '11 12:09

dletozeun


1 Answers

The built-in cache is not used on any of the constructors that accept an XmlRootAttribute. Your best bet is to use the constructor that accepts a single XmlTypeMapping parameter:

public XmlSerializer(XmlTypeMapping xmlTypeMapping)

And to wrap it in your own constructor that accepts a XmlRootAttribute, and constructs the XmlTypeMapping from it using XmlReflectionImporter:

public class CachedRootXmlSerializer : XmlSerializer
{
    private static Dictionary<int, XmlTypeMapping> rootMapCache = new Dictionary<int,XmlTypeMapping>();

    private static XmlTypeMapping GetXmlTypeMappingFromRoot(Type type, XmlRootAttribute xmlRootAttribute)
    {
        XmlTypeMapping result = null;
        int hash = 17;

        unchecked
        {
            hash = hash * 31 + type.GUID.GetHashCode();
            hash = hash * 31 + xmlRootAttribute.GetHashCode();
        }

        lock (rootMapCache)
        {
            if (!rootMapCache.ContainsKey(hash))
            {
                XmlReflectionImporter importer = new XmlReflectionImporter(null, null);
                rootMapCache[hash] = importer.ImportTypeMapping(type, xmlRootAttribute, null);
            }
            result = rootMapCache[hash];
        }

        return result;
    }

    CachedRootXmlSerializer(Type type, XmlRootAttribute xmlRootAttribute)
        : base(GetXmlTypeMappingFromRoot(type, xmlRootAttribute))
    {
    }
}

Enjoy!

like image 57
DaveMorganTexas Avatar answered Nov 15 '22 06:11

DaveMorganTexas