Precompile XmlSerializers with XmlAttributeOverrides

爱⌒轻易说出口 提交于 2019-11-26 21:36:43

问题


When constructing XmlSerializer instances in .NET, assemblies for serializing and deserializing the specified type are generated dynamically. This is a time-consuming process. The sgen.exe tool from Microsoft can be used to precompile XmlSerializer instances to use them later without generating them dynamically. Unfortunately this is not possible with XmlSerializer instances which use XmlAttributeOverrides.

Is there any way to precompile these XmlSerializer instances to avoid generation at run-time?


回答1:


Andreas, this is not a problem of the sgen tool itself, this is due to the XmlSerializer implementaion.

When you create an instance of XmlSerializer, using the constructor with only one Type argument, it goes and checks the cache and looks for the pre-generated assemblies. But when you use the constructor with XmlAttributeOverrides, XmlSerializer doesn't check any caches and goes generating the temp assembly right away.

Most probably, that's because of the quite radical changes in the serialization logic that you can achive using the XmlAttributeOverrides argument, which cannot be "foreseen" in compile-time by tools like sgen.

If you need to have things pre-compiled, you [sigh] have to avoid the XmlAttributeOverrides. If this is not possible, try creating the required XmlSerializer instances ahead-of-time, maybe in a background thread.

Just for your interest, here is the code for the default constructor (checks cache and tries to find a pre-generated assembly):

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);
        }
    }
}

And here is the constructor used with XmlAttributeOverrides (always generates serialization assembly):

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);
}


来源:https://stackoverflow.com/questions/678676/precompile-xmlserializers-with-xmlattributeoverrides

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!