指定XmlRootAttribute时XmlSerializer性能问题

Dou*_*ugc 18 .net c# xml performance xml-serialization

我目前有一个非常奇怪的问题,我似乎无法弄清楚如何解决它.

我有一个相当复杂的类型,我正在尝试使用XmlSerializer类进行序列化.这实际上运行正常,类型序列化正确,但似乎需要长时间这样做; 大约5秒钟,具体取决于对象中的数据.

经过一些分析后,我已经缩小了问题 - 奇怪的是 - 在调用XmlSerializer.Serialize时指定一个XmlRootAttribute.我这样做是为了将从ArrayOf序列化的集合的名称更改为更有意义的东西.一旦我删除参数,操作几乎是即时的!

任何想法或建议都会非常好,因为我完全被这个问题所困扰!

Dou*_*ugc 25

只是遇到这个问题的其他人; 有了上面的答案和MSDN中的示例我设法使用以下类解决此问题:

public static class XmlSerializerCache
{
    private static readonly Dictionary<string, XmlSerializer> cache =
                            new Dictionary<string, XmlSerializer>();

    public static XmlSerializer Create(Type type, XmlRootAttribute root)
    {
        var key = String.Format(
                  CultureInfo.InvariantCulture,
                  "{0}:{1}",
                  type,
                  root.ElementName);

        if (!cache.ContainsKey(key))
        {
            cache.Add(key, new XmlSerializer(type, root));
        }

        return cache[key];
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,而不是使用默认的XmlSerializer构造函数,它采用XmlRootAttribute,我使用以下代码:

var xmlRootAttribute = new XmlRootAttribute("ExampleElement");
var serializer = XmlSerializerCache.Create(target.GetType(), xmlRootAttribute);
Run Code Online (Sandbox Code Playgroud)

我的应用程序现在再次执行!

  • 这是一个非常轻微的优化.如果要执行大量这些查找,请尝试获取if子句中的值.如果你只想知道项目是否存在,但是没有得到它,那么ContainsKey会更有效,但是因为你总是返回值,所以tryget更好:http://dotnetperls.com/dictionary-lookup (6认同)

Jef*_*nal 19

正如对原始问题的后续评论中所提到的,.NET在创建XmlSerializers时会发出程序集,如果使用以下两个构造函数之一创建生成的程序集,则会缓存生成的程序集:

XmlSerializer(Type)
XmlSerializer(Type, String)
Run Code Online (Sandbox Code Playgroud)

使用其他构造函数生成的程序集不会被缓存,因此.NET每次都必须生成新的程序集.

为什么?这个答案可能并不十分令人满意,但是在Reflector中对此进行了解,您可以看到用于存储和访问生成的XmlSerializer程序集(TempAssemblyCacheKey)的键只是一个简单的复合键,它是从可序列化类型和(可选)其命名空间构建的.

因此,没有机制来判断缓存XmlSerializer是否SomeType具有特殊XmlRootAttribute或默认缓存.

很难想到密钥无法容纳更多元素的技术原因,所以这可能只是一个没有人有时间实现的功能(特别是因为它涉及改变其他稳定的类).

您可能已经看过这个,但是如果没有,那么XmlSerializer类文档讨论了一种解决方法:

如果使用任何其他构造函数,则会生成同一程序集的多个版本,并且永远不会卸载,这会导致内存泄漏和性能下降.最简单的解决方案是使用前面提到的两个构造函数之一.否则,必须将程序集缓存在a中Hashtable,,如以下示例所示.

(我在这里省略了这个例子)