2

I am trying to find the best practices or some accepted design patterns for serializing classes that aren't built for serialization. Below is the method I've currently implemented:

For example, consider some simple class where I want a constructor:

public class Coord
{

    public int x { get; private set;}
    public int y { get; private set;}

    public Coord(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

}

If I want to serialize this, I can't without exposing the fields as fully public, and providing a parameterless constructor.

Is it acceptable practice to create some other class just to hold the values I want serialized:

public class DataItem
{
    public int x;
    public int y;
}

Then perhaps have methods that build and load between these classes

public static DataItem saveCoord (Coord c)
    {
        DataItem result = new DataItem ();
        result.x = c.x;
        result.y = c.y;

        return result;
    }

public static Coord loadCoord (DataItem di)
    {
        Coord result = new Coord (di.x, di.y);
        return result;
    }

Then I can perform any serialization actions on my DataItem class.

What might be criticisms of this method? Are there better, established patterns?

Sorry if my question is poor, I'm a fresh learner!

jetimmins
  • 21
  • 3
  • You should have a look at the `ISerializable` interface, https://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable(v=vs.110).aspx – Jeroen van Langen Jun 01 '16 at 11:01
  • Thank you Jeroen, that looks like a really useful interface. I edited my code to refine my question, maybe this solution is simpler in my case. – jetimmins Jun 01 '16 at 12:33
  • There's no general solution for this. Some serializers (`DataContractSerializer` e.g.) support surrogate serialization types. See [Data Contract Surrogates](https://msdn.microsoft.com/en-us/library/ms733064.aspx). `XmlSerializer` does not, but you could add a surrogate *property* on the containing type, see [Most elegant xml serialization of Color structure](https://stackoverflow.com/questions/3280362). Alternatively, you could [implement `IXmlSerializable`](https://stackoverflow.com/questions/279534) on the `Coord` type. Note that `XmlSerialize` does not support `ISerializable`. – dbc Jun 01 '16 at 19:51

2 Answers2

0

As Jeroen van Langen pointed out the ISerializable is what you need to implement if you want to take full control of how the serialization happens but can be quite a non-trivial task, more so if you need to do this to many classes.

I personally would generally lean towards your second example but I would not try to make the data item class a transport class if I could just pass around Coord instead since they seem to be the 'data' in this case. Make the coords public and serializable instead of the data item.

Paul Swetz
  • 2,234
  • 1
  • 11
  • 28
  • Thank you very much Paul. ISerializible does look difficult to someone just breaching the topic. I think I'll need to approach it slowly. My justification for using this intermediary DataItem class here is that in reality, the class I want to serialise is much bigger than this Coord class, with many variables I'd like to keep private set methods for that might have validation code. – jetimmins Jun 01 '16 at 13:14
0

So it seems like there are other classes that can serialize to XML without these restrictions that XmlSerializer imposes - namely DataContractSerializer. Using that in place of XmlSerializer and marking my class and private attributes with [DataContract] and [Datamember] respectively works great.

I've been told there are some restrictions to this method but in my case it's a neater solution.

Thanks!

jetimmins
  • 21
  • 3