Проблема Работы XmlSerializer, когда Определение XmlRootAttribute

USB 2.0 (или RS232 для более старых).

18
задан John Saunders 14 October 2009 в 01:23
поделиться

2 ответа

Только для всех, кто столкнется с этой проблемой; вооружившись ответом выше и примером из 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];
    }
}

Затем вместо использования конструктора XmlSerializer по умолчанию, который принимает XmlRootAttribute, я использую следующее:

var xmlRootAttribute = new XmlRootAttribute("ExampleElement");
var serializer = XmlSerializerCache.Create(target.GetType(), xmlRootAttribute);

Теперь мое приложение снова выступаем!

25
ответ дан 30 November 2019 в 06:46
поделиться

As mentioned in the follow-up comment to the original question, .NET emits assemblies when creating XmlSerializers, and caches the generated assembly if it is created using one of these two constructors:

XmlSerializer(Type)
XmlSerializer(Type, String)

Assemblies generated using the other constructors are not cached, so .NET has to generate new assemblies every time.

Why? This answer probably isn't very satisfying, but peering at this in Reflector, you can see that the key used to store and access the generated XmlSerializer assemblies (TempAssemblyCacheKey) is just a simple composite key built from the serializable type and (optionally) its namespace.

Thus, there's no mechanism to tell whether a cached XmlSerializer for SomeType has a special XmlRootAttribute or the default one.

It's hard to think of a technical reason that the key couldn't accommodate more elements, so this is probably just a feature that no one had time to implement (especially since it would involve changing otherwise stable classes).

You may have seen this, but in case you haven't, the XmlSerializer class documentation discusses a workaround:

If you use any of the other constructors, multiple versions of the same assembly are generated and never unloaded, which results in a memory leak and poor performance. The easiest solution is to use one of the previously mentioned two constructors. Otherwise, you must cache the assemblies in a Hashtable,as shown in the following example.

(I've omitted the example here)

19
ответ дан 30 November 2019 в 06:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: