I found a clean way to achieve what you are looking for without breaking your design.
Using this method will ensure that your constructor will be called and your readonly field properly set.
What you need is to actually serialize and deserialize [DataMember]
marked fields from a DataModel class.
That will prevent any unintended behavior to happen knowing that DataContractSerializer does not call the constructor when deserializing.
namespace MyApp.DataModel
{
//It is not mandatory to specify the DataContract since a default one will be
//provided on recent version of .Net, however it is a good practice to do so.
[DataContract(Name = "MyClassDataModel", Namespace = "MyApp.DataModel")]
public class MyClassDataModel
{
[DataMember]
public bool DataMemberExample{ get; set; }
}
}
For deserializing and serializing you can now use this class to hold your values.
Upon loading you can create a new data model object and pass it to your class which needs to have its constructor called.
public MyObjectThatNeedToBeConstructed LoadData(){
// ...
// get your reader (Stream) from the file system or wherever it's located
var deserializer = new DataContractSerializer(typeof(MyClassDataModel));
var storedModel = (MyClassDataModel)deserializer.ReadObject(reader);
return new MyObjectThatNeedToBeConstructed(storedModel);
}
Upon saving you can extract the required data from your class that contain the ReadOnly field.
public void SaveData(MyObjectThatNeedToBeConstructed myObject){
// ...
// get your writer (Stream) from memory or wherever it's located
var serializer = new DataContractSerializer(typeof(MyClassDataModel));
var dataModel = new MyClassDataModel{ DataMemberExample = myObject.DataMember};
serializer.WriteObject(writer, dataModel);
}
Of course, you will have to add an overload to the constructor and you might have to tweak the example a bit, but I think you got the picture.
FormatterServices.GetUninitializedObject
to "construct" an empty object and does not invoke a constructor or run field initializers. As far as I understand, areadonly
field can only be initialized in one of those two ways (but hopefully there's another way I'm not familiar with). – Mahrattareadonly
field. I can certainly use theOnDeserialized
attribute to initialize object state the wayDataContractSerializer
wants me to, but then I see no way to also use thereadonly
attribute to protect that state from post-initialization modification. – Mahratta