Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using .Net what limitations (if any) are there in using the XmlSerializer?

Using .Net what limitations (if any) are there in using the XmlSerializer? For example, can you serialize Images to XML?

like image 336
Gary Willoughby Avatar asked Sep 20 '08 20:09

Gary Willoughby


People also ask

Why do we use XmlSerializer class?

Serialization/ De-serialization allow communication with another application by sending and receiving data. With XmlSerializer, you can control how objects are encoded into XML. Call the Serialize method with the parameters of the StreamWriter and object to serialize.

Is XmlSerializer thread safe?

Since XmlSerializer is one of the few thread safe classes in the framework you really only need a single instance of each serializer even in a multithreaded application.

How does the XmlSerializer work C#?

The XmlSerializer creates C# (. cs) files and compiles them into . dll files in the directory named by the TEMP environment variable; serialization occurs with those DLLs. These serialization assemblies can be generated in advance and signed by using the SGen.exe tool.

Can I make XmlSerializer ignore the namespace on deserialization?

Yes, you can tell the XmlSerializer to ignore namespaces during de-serialization. Note this is the kind of thing I meant. You are not telling the XmlSerializer to ignore namespaces - you are giving it XML that has no namespaces.


3 Answers

I generally find the XmlSerializer to be a poor choice for any POCO that's more than just a DTO. If you require specific XML, you can go the Xml*Attribute and/or IXmlSerializable route - but you're left with an object pretty mangled.

For some purposes, it still an obvious choice - even with it's limitations. But, for simply storing and reloading data, I've found BinaryFormatter to be a much easier choice with less pitfalls.

Here's a list of some annoyances with XmlSerializer - most I've been bitten by at one point or another, others I found over at MSDN:

  • Requires a public, no args constructor
  • Only serializes public read/write properties and fields
  • Requires all types to be known
  • Actually calls into get_* and set_*, so validation, etc. will be run. This may be good or bad (think about the order of the calls as well)
  • Will only serialize IEnumerable or ICollection collections conforming to specific rules

The XmlSerializer gives special treatment to classes that implement IEnumerable or ICollection. A class that implements IEnumerable must implement a public Add method that takes a single parameter. The Add method's parameter must be of the same type as is returned from the Current property on the value returned from GetEnumerator, or one of that type's bases.

A class that implements ICollection (such as CollectionBase) in addition to IEnumerable must have a public Item indexed property (indexer in C#) that takes an integer, and it must have a public Count property of type integer. The parameter to the Add method must be the same type as is returned from the Item property, or one of that type's bases. For classes that implement ICollection, values to be serialized are retrieved from the indexed Item property, not by calling GetEnumerator.

  • Does not serialize IDictionary
  • Uses dynamically generated assemblies, which may not get unloaded from the app domain.

To increase performance, the XML serialization infrastructure dynamically generates assemblies to serialize and deserialize specified types. The infrastructure finds and reuses those assemblies. This behavior occurs only when using the following constructors:

XmlSerializer.XmlSerializer(Type) XmlSerializer.XmlSerializer(Type, String)

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.

  • Cannot serialize ArrayList[] or List<T>[]
  • Has other weird edge cases

The XmlSerializer cannot be instantiated to serialize an enumeration if the following conditions are true: The enumeration is of type unsigned long (ulong in C#) and the enumeration contains any member with a value larger than 9,223,372,036,854,775,807.

The XmlSerializer class no longer serializes objects that are marked as [Obsolete].

You must have permission to write to the temporary directory (as defined by the TEMP environment variable) to deserialize an object.

  • Requires reading .InnerException to get any useful info on errors
like image 185
Mark Brackett Avatar answered Oct 17 '22 00:10

Mark Brackett


The XmlSerializer has a few drawbacks.

  1. It must know all the types being serialized. You cannot pass it something by interface that represents a type that the serializer does not know.
  2. It cannot do circular references.
  3. It will serializes the same object multiple times if referenced multiple times in the object graph.
  4. Cannot handle private field serialization.

I (stupidly) wrote my own serializer to get around some of these problems. Don't do that; it is a lot of work and you will find subtle bugs in it months down the road. The only thing I gained in writing my own serializer and formatter was a greater appreciation of the minutia involved in object graph serialization.

I found the NetDataContractSerializer when WCF came out. It does all the stuff from above that XmlSerializer doesn't do. It drives the serialization in a similar fashion to the XmlSerializer. One decorates various properties or fields with attributes to inform the serializer what to serialize. I replaced the custom serializer I had written with the NetDataContractSerializer and was very happy with the results. I would highly recommend it.

like image 44
Jason Jackson Avatar answered Oct 17 '22 01:10

Jason Jackson


Another problem is that calling the constructor of XmlSerializer will compile code at runtime and will generate a temp DLL (in the %temp% folder) with the code to do the de/serialization.

You can watch the code if you add the following lines to app.config:

  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="4"/>
    </switches>
  </system.diagnostics>

This takes a lot of time the first time you serialize a class and needs code with permissions for compiling and writing to disk.

A way to get around that is to precompile these DLL using the sGen.exe tool that comes with VS 2005+.

Look here for more information.

like image 32
Tomer Pintel Avatar answered Oct 17 '22 01:10

Tomer Pintel