使用XmlAttributeOverrides预编译XmlSerializers

9

在.NET中构建XmlSerializer实例时,用于序列化和反序列化指定类型的程序集是动态生成的。这是一个耗时的过程。微软的sgen.exe工具可用于预编译XmlSerializer实例,以便稍后使用它们而无需动态生成它们。不幸的是,对于使用XmlAttributeOverrides的XmlSerializer实例,这是不可能的。

有没有办法预编译这些XmlSerializer实例以避免在运行时生成?


你在这方面有进展了吗? - Rory
1个回答

7

Andreas,这不是sgen工具本身的问题,而是由XmlSerializer实现引起的。

当您使用仅一个Type参数的构造函数创建XmlSerializer实例时,它会检查缓存并查找预生成的程序集。但是,当您使用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);
}

啊,我遇到了同样的问题。不幸的是,我无法使用动态创建序列化程序集,因为我无法启动csc.exe(正在从受保护模式Internet Explorer运行)。有什么建议吗?我在考虑是否可以捕获由XmlSerializer创建的临时.cs文件,将其包含在我的构建中,并直接使用它而不是XmlSerializer。听起来很混乱,但还有其他想法吗?我的问题在这里:http://stackoverflow.com/questions/7333689/generating-an-xml-serialization-assembly-for-a-custom-xmlserializer - Rory

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接