Конструктор XmlSerializer с аргументами XmlTypeMapping и XmlRootAttribute - PullRequest
7 голосов
/ 29 сентября 2011

Я бы хотел предварительно выбрать в C #, XmlTypeMapping из известного набора типов классов, чтобы ускорить десериализацию их XML при создании нового XmlSerializer как XmlReflectionImporter.ImportTypeMapping (что происходит во время XmlSerializer конструирования наТип класса) довольно трудоемкий и, кажется, происходит при каждой XmlSerializer конструкции.

Кроме того, анализируемое мной XML-содержимое вынуждает меня использовать аргумент XmlRootAttribute, чтобы установить имя корневого элемента xml для анализа какэто не всегда то же самое.Для этого я могу использовать конструктор XmlSerializer(Type, XmlRootAttribute) для десериализации моего объекта.

Однако я также хотел бы воспользоваться преимуществом предварительной выборки XmlTypeMapping, и я не вижу никакого конструктора XmlSerializer, такого как: XmlSerializer( XmlTypeMapping, XmlRootAttribute ) или что-то близкое.Как я могу этого достичь?

Любая помощь будет принята с благодарностью!Спасибо.

1 Ответ

3 голосов
/ 20 октября 2012

Встроенный кэш не используется ни одним из конструкторов, которые принимают атрибут XmlRootAttribute. Лучше всего использовать конструктор, который принимает один параметр XmlTypeMapping:

public XmlSerializer(XmlTypeMapping xmlTypeMapping)

И обернуть его в свой собственный конструктор, который принимает XmlRootAttribute и создает из него XmlTypeMapping с помощью 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))
    {
    }
}

Наслаждайтесь!

...