Reputation: 1282
I need to initialize private readonly field after Deserialization. I have folowing DataContract:
[DataContract]
public class Item
{
public Item()
{
// Constructor not called at Deserialization
// because of FormatterServices.GetUninitializedObject is used
// so field will not be initialized by constructor at Deserialization
_privateReadonlyField = new object();
}
// Initialization will not be called at Deserialization (same reason as for constructor)
private readonly object _privateReadonlyField = new object();
[DataMember]
public string SomeSerializableProperty { get; set; }
[OnDeserializing]
public void OnDeserializing(StreamingContext context)
{
// With this line code even not compiles, since readonly fields can be initialized only in constructor
_privateReadonlyField = new object();
}
}
All what I need, that after Deserialization _privateReadonlyField is not null.
Any suggestions about this - is it possible at all? Or I need to remove "readonly" key, which is not a good option.
Upvotes: 13
Views: 3956
Reputation: 23148
Serialization is able to read in values for read-only fields because it uses reflection, which ignores accessibility rules. It can be argued that the following is, therefore, justified as part of the serialization process, even though I would recommend strongly against it in almost any other circumstance:
private readonly Doodad _oldField;
[OptionalField(VersionAdded = 2)]
private readonly Widget _newField;
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (_oldField != null && _newField == null)
{
var field = GetType().GetField("_newField",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.DeclaredOnly |
System.Reflection.BindingFlags.NonPublic);
field.SetValue(this, new Widget(_oldField));
}
}
Upvotes: 10
Reputation: 9296
Any field declared as private readonly
can be instantiated in the same line where it was declared or inside a constructor. Once that is done it cannot be changed.
From MSDN:
The readonly keyword is a modifier that you can use on fields. When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
That means that you will have to remove readonly
keyword to get it to work.
Upvotes: 7