Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutability and XML Serialization

I have several classes that are immutable once their initial values are set. Eric Lippert calls this write-once immutability.

Implementing write-once immutability in C# usually means setting the initial values via the constructor. These values initialize readonly fields.

But if you need to serialize a class like this to XML, using either the XmlSerializer or the DataContractSerializer, you must have a parameterless constructor.

Does anyone have suggestions for how to work around this problem? Are there other forms of immutability that work better with serialization?

EDIT: As @Todd pointed out, the DataContractSerializer does not require a parameterless constructor. According to the DataContractSerializer documentation on MSDN, DataContractSerializer "does not call the constructor of the target object."

like image 206
dthrasher Avatar asked Aug 18 '09 14:08

dthrasher


People also ask

What is XML serialization?

XML serialization is the process of converting XML data from its representation in the XQuery and XPath data model, which is the hierarchical format it has in a Db2® database, to the serialized string format that it has in an application.

What is the difference between binary serialization and XML serialization?

Xml Serializer serializes only public member of object but Binary Serializer serializes all member whether public or private. In Xml Serialization, some of object state is only saved but in Binary Serialization, entire object state is saved.

Is XML a serialization format?

XML serialization serializes only the public fields and property values of an object into an XML stream. XML serialization does not include type information. For example, if you have a Book object that exists in the Library namespace, there is no guarantee that it is deserialized into an object of the same type.

Why is immutability important C#?

Learn the importance of immutability and how to take advantage of it in your C# applications. Immutability is a feature of functional programming languages that makes programs easier to write, test, and maintain. However, immutability is not supported by many imperative programming languages.


4 Answers

Assuming this is your "immutable" object :

public class Immutable
{
    public Immutable(string foo, int bar)
    {
        this.Foo = foo;
        this.Bar = bar;
    }

    public string Foo { get; private set; }
    public int Bar { get; private set; }
}

You can create a dummy class to represent that immutable object during serialization/deserialization :

public class DummyImmutable
{
    public DummyImmutable(Immutable i)
    {
        this.Foo = i.Foo;
        this.Bar = i.Bar;
    }

    public string Foo { get; set; }
    public int Bar { get; set; }

    public Immutable GetImmutable()
    {
        return new Immutable(this.Foo, this.Bar);
    }
}

When you have a property of type Immutable, don't serialize it, and instead serialize a DummyImmutable :

[XmlIgnore]
public Immutable SomeProperty { get; set; }

[XmlElement("SomeProperty")]
public DummyImmutable SomePropertyXml
{
    get { return new DummyImmutable(this.SomeProperty); }
    set { this.SomeProperty = value != null ? value.GetImmutable() : null; }
}

OK, this is a bit long for something that looks so simple... but it should work ;)

like image 64
Thomas Levesque Avatar answered Oct 17 '22 07:10

Thomas Levesque


If the class is truly immutable, just use public readonly fields marked with attributes.

 [DataContract()]
 public class Immutable
 {
      [DataMember(IsRequired=true)]
      public readonly string Member;

      public Immutable(string member)
      {
           Member = member;
      }
 }
like image 42
nietras Avatar answered Oct 17 '22 07:10

nietras


"Realio-trulio" immutability involves the constructor. Popsicle immutability is where you can do, for example:

Person p = new Person();
p.Name = "Fred";
p.DateOfBirth = DateTime.Today;
p.Freeze(); // **now** immutable (edit attempts throw an exception)

(or the same with an object initializer)

This fits DataContractSerializer quite well, as long as you handle to on-serialized callback to do the Freeze. XmlSerializer doesn't do serialization callbacks, so is more work.

Either would suit if you use custom serialization (IXmlSerializable), though. Likewise, custom serialization is broadly doable with realio-trulio immutability, but is painful - and it is a bit of a lie, as it is "create once, then call interface method" - so not really properly immutable.

For true immutability, use a DTO.

like image 41
Marc Gravell Avatar answered Oct 17 '22 06:10

Marc Gravell


I recommend taking a look at the discussion here: Why XML-Serializable class need a parameterless constructor.

You should consider using DataContractSerializer. As far as I can tell from the docs, this do not require a parameterless constructor, and can serialize/deserialize private members.

like image 21
Todd Owen Avatar answered Oct 17 '22 08:10

Todd Owen