Custom object in ComponentSettings<MySettings>

Is it possible to use a custom class as a member of ComponentSettings and have it serialized/deserialized?
The custom class use the [Serializable] attribute and is serialized correctly into the XML-file. But I cannot get it deserialized from the file, the custom class object is always null?? I must be missing something. Other members like int, string are serialized and deserialized correctly.

1 Like

This is possible, but it hast nothing to do with SerializableAttribute which is only used for binary serialization.

I have some hints around serialization of properties.

  1. It needs to be a public property with a getter and setter.
  2. The property type needs have a public parameterless constructor or have a custom de/serializer plugin.
  3. (Not really a requirement, but could help) generally avoid doing fancy things in the setter and getters.

Actual, I think that’s all :slight_smile:


@rolf_madsen I just came across a similar issue when my custom settings were not stored in XML . I figured out it was caused by a field with a private setter and now I found your post that confirms that. It’s a bit confusing it wasn’t causing any errors…

I’d like to understand why the ability to serialize requires to have a public setter. Could you please elaborate on that?

The reason to have this field as private was mainly to protect it from editing via UI. What would you recommend to achieve that, knowing that private setter isn’t an option?

First of all, you can use [Browsable(false)] to prevent users from modifying and viewing properties that needs to be serialized. You can also use [XmlIgnore] to prevent a public property from being saved.

Now the reason why:

Public properties are the public API of a class. Other classes are allowed to modify and read them and this is safe. The class is designed to be interacted with in this way.
Private properties are the internals of an object and outside objects are not normally allowed to modify them and this is also not really safe to do, because it is not designed to support that.

The standard .NET XmlSerializer, works in this way and that is also how we decided to do it. BinaryFormatter does it in a different way, but is no longer supported.

There is nothing technically limiting us to only read and write public properties, but as a developer I would find it quite surprising if something outside of my class started modifying the internals of my objects, so that is another reason to avoid it.

Additionally, serializing private properties means that you could break the code (unable to load previous test plans) by just renaming private APIs, so this would make everything harder to maintain.

Unfortunately Browsable attribute is not helpful in this case as I’d really like users to see the data – but I don’t want them to modify it. Is there any other way to achieve that?

Thanks for sharing the reasoning. It’s just a bit confusing that you need a public setter to be able to serialize/write data, but if you realize that you’ll inevitably need to deserialize, it starts making some sense.

That is also a supported scenario, then you just need to make a property with a public getter, a private setter, and since it is not a ‘setting’ (cannot be set) you need to add [Browsable(true)].

That’s exactly what I did, but this way the entire settings class is not being stored to XML. Or am I missing something?

No, that does not sound right, maybe you can share some code that shows this scenario?

I haven’t managed to reproduce my exact issue in an isolated example, but if I set MyInt property of OpenTap.Plugins.PluginDevelopment.ExampleSettings to have a private setter and add Browsable(true), I can see it in the UI but it doesn’t appear in the XML. Is this behavior expected? If yes, it’s unfortunately not what I’m looking for as I need this data to be stored.

Ah yes. OK, I understand now. What about something like this?

   public int A => B;
   public int B {get;set;}

@rolf_madsen That does the trick and it’s even elegant in some way. Thank you.