【问题标题】:Precompile XmlSerializers with XmlAttributeOverrides使用 XmlAttributeOverrides 预编译 XmlSerializer
【发布时间】:2010-10-15 06:54:15
【问题描述】:

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

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

【问题讨论】:

  • 你在这方面有什么进展吗?

标签: .net xml-serialization sgen


【解决方案1】:

Andreas,这不是 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);
}

【讨论】:

  • 啊,我也遇到了同样的问题。不幸的是,我无法使用序列化程序集的动态创建,因为我无法启动 csc.exe(从受保护模式 Internet Explorer 运行)。有什么建议?我想我可以捕获由 XmlSerializer 创建的临时 .cs 文件,将其包含在我的构建中并直接使用它而不是 XmlSerializer。听起来很乱,但还有其他想法吗?我的qn在这里:stackoverflow.com/questions/7333689/…
猜你喜欢
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
相关资源
最近更新 更多