Предварительная компиляция XmlSerializers с XmlAttributeOverrides

При создании экземпляров XmlSerializer в .NET сборки для сериализации и десериализации указанного типа создаются динамически. Это трудоемкий процесс. Инструмент sgen.exe от Microsoft можно использовать для предварительной компиляции экземпляров XmlSerializer, чтобы использовать их позже без их динамического создания. К сожалению, это невозможно с экземплярами XmlSerializer, которые используют XmlAttributeOverrides.

Есть ли способ предварительно скомпилировать эти экземпляры XmlSerializer, чтобы избежать генерации во время выполнения?


person Andreas Stelter    schedule 24.03.2009    source источник
comment
Вы продвинулись дальше с этим?   -  person Rory    schedule 08.09.2011


Ответы (1)


Андреас, это не проблема самого инструмента sgen, это связано с реализацией XmlSerializer.

Когда вы создаете экземпляр XmlSerializer, используя конструктор только с одним аргументом Type, он проверяет кэш и ищет предварительно созданные сборки. Но когда вы используете конструктор с XmlAttributeOverrides, XmlSerializer не проверяет кэши и сразу создает временную сборку.

Скорее всего, это связано с довольно радикальными изменениями в логике сериализации, которых можно добиться с помощью аргумента XmlAttributeOverrides, которые не могут быть «предусмотрены» во время компиляции такими инструментами, как sgen.

Если вам нужно что-то предварительно скомпилировать, вам [вздох] следует избегать XmlAttributeOverrides. Если это невозможно, попробуйте заранее создать необходимые экземпляры XmlSerializer, возможно, в фоновом потоке.

Просто для вашего интереса вот код конструктора по умолчанию (проверяет кеш и пытается найти предварительно сгенерированную сборку):

public XmlSerializer(Type type, string defaultNamespace)
{
    this.events = new XmlDeserializationEvents();
    if (type == null)
    {
        throw new ArgumentNullException("type");
    }
    this.mapping = GetKnownMapping(type, defaultNamespace);
    if (this.mapping != null)
    {
        this.primitiveType = type;
    }
    else
    {
        this.tempAssembly = cache[defaultNamespace, type];
        if (this.tempAssembly == null)
        {
            lock (cache)
            {
                this.tempAssembly = cache[defaultNamespace, type];
                if (this.tempAssembly == null)
                {
                    XmlSerializerImplementation implementation;
                    Assembly assembly = TempAssembly.LoadGeneratedAssembly(type, defaultNamespace, out implementation);
                    if (assembly == null)
                    {
                        this.mapping = new XmlReflectionImporter(defaultNamespace).ImportTypeMapping(type, null, defaultNamespace);
                        this.tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace);
                    }
                    else
                    {
                        this.mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace);
                        this.tempAssembly = new TempAssembly(new XmlMapping[] { this.mapping }, assembly, implementation);
                    }
                }
                cache.Add(defaultNamespace, type, this.tempAssembly);
            }
        }
        if (this.mapping == null)
        {
            this.mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace);
        }
    }
}

А вот конструктор, используемый с XmlAttributeOverrides (всегда генерирует сборку сериализации):

public XmlSerializer(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace, string location, Evidence evidence)
{
    this.events = new XmlDeserializationEvents();
    if (type == null)
    {
        throw new ArgumentNullException("type");
    }
    XmlReflectionImporter importer = new XmlReflectionImporter(overrides, defaultNamespace);
    for (int i = 0; i < extraTypes.Length; i++)
    {
        importer.IncludeType(extraTypes[i]);
    }
    this.mapping = importer.ImportTypeMapping(type, root, defaultNamespace);
    if (location != null)
    {
        this.DemandForUserLocation();
    }
    this.tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace, location, evidence);
}
person Max Galkin    schedule 20.09.2009
comment
О, я столкнулся с этой же проблемой. К сожалению, я не могу использовать динамическое создание сборок сериализации, потому что не могу запустить csc.exe (запускаю из защищенного режима Internet Explorer). Какие-либо предложения? Я думаю, что мог бы захватить временный файл .cs, созданный XmlSerializer, включить его в свою сборку и использовать вместо XmlSerializer напрямую. Звучит грязно, но есть другие идеи? Мой вопрос здесь: stackoverflow.com/questions/7333689/ - person Rory; 08.09.2011