SavableModelBase: how to serialize not-serializable properties?

Topics: Feature requests
Nov 8, 2012 at 6:25 AM

Hi Geert,

I have a model deriving from SavableModelBase.
Among simple properties, there is one which is not serializable.
But it is possible to serialize it using helper methods.

Think about it as if it was a Timestamp using the .net default XML serializer with POCO properties.
In such a situation I add a TimestampString property which sets and parses the original Timestamp property and mark the Timestamp property as not-to-serialize.

How to get this to work using Catel with registered properties? 

Thanks,
Alex.

 

Coordinator
Nov 8, 2012 at 7:36 AM

You can do the same thing with Catel. In the RegisterProperty method, you can let Catel know whether the property should be included in the backup / serialization. For the main property, you can set it to false.

You can create an additional property which *is* serializable.

Maybe in the future we will implement a custom serialization part, but don't expect that soon without real requirements.

Nov 8, 2012 at 4:31 PM

Hi Geert,

cannot get it to work.
Please check this sample (.NET console app)

Problems:
1) when the NotSerializableUsingClassProperty exists, no instance of the Settings class is creatable.
2) when the NotSerializableUsingInterface != null, serialization fails.
3) the serialization should use the string-convert properties SerializeNotSerializableUsingInterface and SerializeNotSerializableUsingClass

thanks, alex.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using Catel.Data;

namespace CatelNotSerializableSpike
{
    class Program
    {
        static void Main(string[] args)
        {
            var saveFileDPNE = System.Reflection.Assembly.GetExecutingAssembly().Location + ".settings.xml";

            // create settings
            var settings = new Settings();
            settings.Name = "Test";
            settings.NotSerializableUsingInterface = new NotSerializable { Content = "some content on NotSerializableUsingInterface" };
            settings.NotSerializableUsingClass = new NotSerializable { Content = "some content on NotSerializableUsingClass" };

            // save it
            System.Diagnostics.Debug.WriteLine("Saving settings to: [" + saveFileDPNE + "]");
            settings.Save(saveFileDPNE, SerializationMode.Xml);

            // load it
            var loadedSettings = Settings.Load(saveFileDPNE);
            Console.WriteLine("Should be the same: {0}={1}",
                              settings.NotSerializableUsingInterface.Content,
                              loadedSettings.NotSerializableUsingInterface.Content);
            Console.WriteLine("Should be the same: {0}={1}",
                              settings.NotSerializableUsingClass.Content,
                              loadedSettings.NotSerializableUsingClass.Content);
            Console.ReadLine();

        }
    }

    [AllowNonSerializableMembers]
    class Settings : Catel.Data.SavableModelBase<Settings>
    {
        #region Constructors

        public Settings()
        {
        }

        public Settings(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        #endregion

        #region simple serializable property

        // Name
        public static readonly PropertyData
            NameProperty = RegisterProperty(@"Name",
                                            typeof(string),
                                            default(string));

        public string Name
        {
            get { return GetValue<string>(NameProperty); }
            set { SetValue(NameProperty, value); }
        }

        #endregion


        #region NotSerializableUsingInterface

        // NotSerializableUsingInterface
        public static readonly PropertyData
            NotSerializableUsingInterfaceProperty = RegisterProperty(@"NotSerializableUsingInterface",
                                                                     typeof(INotSerializable),
                                                                     default(INotSerializable),
                                                                     includeInSerialization: false);

        public INotSerializable NotSerializableUsingInterface
        {
            get { return GetValue<INotSerializable>(NotSerializableUsingInterfaceProperty); }
            set { SetValue(NotSerializableUsingInterfaceProperty, value); }
        }

        // alternate POCO property for serializing the NotSerializableUsingInterface type
        public string SerializeNotSerializableUsingInterface
        {
            get { return this.NotSerializableUsingInterface != null ? this.NotSerializableUsingInterface.Content : null; }
            set { this.NotSerializableUsingInterface = new NotSerializable {Content = value}; }
        }

        #endregion


        #region NotSerializableUsingClass

        // NotSerializableUsingClass
        public static readonly PropertyData
            NotSerializableUsingClassProperty = RegisterProperty(@"NotSerializableUsingClass",
                                                                 typeof(NotSerializable),
                                                                 default(NotSerializable),
                                                                 includeInSerialization: false);

        public NotSerializable NotSerializableUsingClass
        {
            get { return GetValue<NotSerializable>(NotSerializableUsingClassProperty); }
            set { SetValue(NotSerializableUsingClassProperty, value); }
        }

        // alternate POCO property for serializing the NotSerializableUsingClass type
        public string SerializeNotSerializableUsingClass
        {
            get { return this.NotSerializableUsingClass != null ? this.NotSerializableUsingClass.Content : null; }
            set { this.NotSerializableUsingClass = new NotSerializable {Content = value}; }
        }

        #endregion

    }

    interface INotSerializable
    {
        string Content { get; set; }
    }

    class NotSerializable : INotSerializable
    {
        public string Content { get; set; }
    }
}

Nov 13, 2012 at 5:25 AM

I really would like to get this working....
Do you think you can look after my sample code? 

Coordinator
Nov 13, 2012 at 7:21 AM

Yes, will try, but had a very busy weekend. First I want to fix the StackOverflow issue that some people are experiencing. Then I will take a look at this.

Dec 1, 2012 at 7:10 PM

Hi Geert,

when do you think you can take a look at this issue?

thanks, alex.

Coordinator
Dec 3, 2012 at 5:13 PM

I am not sure yet. To be honest I have a few paying customers waiting which of course have a higher priority. The good news is that it is still on my list. The bad news is that my list is quite big...

Coordinator
Jan 28, 2013 at 8:45 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Jul 26, 2013 at 1:55 PM
It took some time but we have completely rewritten the serialization engine which also fixes this sissue.