Search code examples
iosserializationxamarin.iosserializablecllocation

MonoTouch : How to serialize a type (like CLLocation) not marked as Serializable?


I'm working to an iPhone project using MonoTouch, and I need to serialize and save a simple object belonging to a c# class with a CLLocation type as data member:

[Serializable]
public class MyClass
{
    public MyClass (CLLocation gps_location, string location_name)
    {
        this.gps_location = gps_location;
        this.location_name = location_name;
    }

    public string location_name;
    public CLLocation gps_location;
}

This is my binary serialization method:

static void SaveAsBinaryFormat (object objGraph, string fileName)
    {
        BinaryFormatter binFormat = new BinaryFormatter ();
        using (Stream fStream = new FileStream (fileName, FileMode.Create, FileAccess.Write, FileShare.None)) {
            binFormat.Serialize (fStream, objGraph);
            fStream.Close ();
        }
    }

But when I execute this code (myObject is an instance of the above class):

try {
            SaveAsBinaryFormat (myObject, filePath);
            Console.WriteLine ("object Saved");
        } catch (Exception ex) {
            Console.WriteLine ("ERROR: " + ex.Message);
        }

I get this exception:

ERROR: Type MonoTouch.CoreLocation.CLLocation is not marked as Serializable.

Is there a way to serialize a class with CLLocation?


Solution

  • Since a class is not marked with the SerializableAttribute, it cannot be serialized. However, with a bit of extra work, you can store the information you need from it and serialize it, at the same time keeping it in your object.

    You do this by creating a property for it, with the appropriate backing stores, depending on the information you want from it. For example, if I only want the coordinates of the CLLocation object, I would create the following:

    [Serializable()]
    public class MyObject
    {
    
        private double longitude;
        private double latitude;
        [NonSerialized()] // this is needed for this field, so you won't get the exception
        private CLLocation pLocation; // this is for not having to create a new instance every time
    
        // properties are ok    
        public CLLocation Location
        {
            get
            {
                if (this.pLocation == null)
                {
                    this.pLocation = new CLLocation(this.latitude, this.longitude);
                }
                return this.pLocation;
    
            } set
            {
                this.pLocation = null;
                this.longitude = value.Coordinate.Longitude;
                this.latitude = value.Coordinate.Latitude;
            }
    
        }
    }