Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XmlSerializer, GenerateSerializer and Collections

We have some setup classes in our project, which are serialized / deserialized with XmlSerializer from some .config-Files. In some of those setup classes we have collections of sub-setups like this:

using System;
using System.Collections.ObjectModel;
using System.Xml.Serialization;

namespace Datev.Framework.Shared.Actions.Setup
{
    [Serializable]
    [XmlSerializerAssembly]
    [XmlRoot("setup")]
    public class SetupXml
    {
        public SetupXml()
        {
            SubSetups = new Collection<SubSetupXml>();
        }

        [XmlArray("subSetups")]
        [XmlArrayItem("subSetup")]
        public Collection<SubSetupXml> SubSetups { get; private set; }
    }

    [Serializable]
    public class SubSetupXml
    {
        [XmlElement("someValue")]
        public string SomeValue { get; set; }
    }
}

We are using the attribute [XmlSerializerAssembly] to have the best performance for reading and writing the setups. And here is my problem: We are using Collection to avoid the CA-Warning "Don't use arrays". When we make the setter of SubSetups public, we get the CA-Warning CA2227 "Don't make the setter of a collection public". If we make the setter of the property SubSetups private (like in the code sample), we'll get an error in the generated serializer. The method "GenerateSerializer" (invoked in a tool of us) the code has a line like this:

if (o.SubSetups == null) o.SubSetups = new Collection<SubSetupXml>();

If we make the setter private, we'll get a CS0200 "Property SubSetups cannont be assigned" during building the serializer. Does anyone know how to make a correct setup with a generated serializer without suppressing a CA-Warning?

like image 659
Fischermaen Avatar asked Dec 18 '12 08:12

Fischermaen


People also ask

What is DataContractSerializer and how its different from XmlSerializer?

DataContractSerializer can able to serialize types that implements Idictionary whereas XML serializer not. DataContractSerializer serializes all members which are marked with [DataMember] attribute even if member is marked private. XML serializer serialize only public members.

Why do we use XmlSerializer class?

XmlSerializer enables you to control how objects are encoded into XML. The XmlSerializer enables you to control how objects are encoded into XML, it has a number of constructors.

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.

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.


2 Answers

It is hard to tell: a "correct" setup depends highly on the context. Just a quick idea: what happens if you move the logic from "GenerateSerializer" to the property getter? Would it be acceptable?

[XmlArray("subSetups")]
[XmlArrayItem("subSetup")]
public Collection<SubSetupXml> SubSetups { 
   get {
      // subSetups needs to be a backing (private) field... is this a problem?
      if (this.subSetups == null) this.subSetups = new Collection<SubSetupXml>();
   }
   private set; 
}

This way, in "GenerateSerializer" you just get the collection. If the collection has not already been created, it will be inside the getter, without needing to create it outside the class. Just an idea, let me know if it is not applicable.

like image 195
Lorenzo Dematté Avatar answered Nov 01 '22 16:11

Lorenzo Dematté


If the situation is as straightforward as it seems then You don't need to check whether (o.SubSetups == null) because You have the line SubSetups = new Collection<SubSetupXml>(); in the SetupXml() constructor (that is, of course, if o is of type SetupXml). If you get rid of that if statement from the GenerateSerializer method and make the setter private You should be fine - there's no way the SubSetups property can be null unless there are some other ways of messing around with it that You didn't mention...

like image 31
Grx70 Avatar answered Nov 01 '22 16:11

Grx70