Serialization
Beginner Programmer
The editor and serialization system uses four attributes to determine what is serialized and visible in the editor.
DataContractAttribute
Adding the DataContractAttribute
to your class
or struct
notifies the serializer that it should serialize the data it contains, and the editor that it should display fields and properties of that type, along with the scenes or assets that might include it.
[Stride.Core.DataContract(Inherited = true)]
public class MySerializedClass
{
public float MyValue;
}
// 'DataContract' is inherited above. You don't need to specify it for a derived class.
public class MyDerivedSerializedClass : MySerializedClass
{
public string MyName;
}
Note
Your IDE may wrongfully add System.Runtime.Serialization
to your list of using
when adding DataContract
.
They are not interchangeable.
Make sure that your DataContract
comes from Stride.Core
, specifying the namespace explicitly like shown above if necessary.
DataMemberAttribute
The DataMemberAttribute
notifies the editor and serializer that the property or field on this DataContract
'ed class
or struct
should be serialized. Note that you can omit this attribute for most public fields and properties, as they will be included by default. See Fields and Properties for specifics.
[Stride.Core.DataContract]
public class MySerializedClass
{
[Stride.Core.DataMember]
internal float MyValue;
}
DataAliasAttribute
The DataAliasAttribute
can be used to ensure you do not break previously serialized data whenever you have to change how that member is named in your source.
[Stride.Core.DataAlias("PreviousNameOfProp")]
public string MyRenamedProp { get; set; }
Note
Alias remaps values only while in the editor; this feature is specific to the YAML serialization system. Alias will be ignored during builds and at runtime.
DataMemberIgnoreAttribute
The DataMemberIgnoreAttribute
notifies the editor and serializer that the property or field on this DataContract
'ed class
or struct
should NOT be serialized.
[Stride.Core.DataContract]
public class MySerializedClass
{
[Stride.Core.DataMemberIgnore]
public float MyValue { get; set; } // This public property will NOT show up in the editor
}
TODO
Rule of Thumb
Serialization and the editor's access and view of your properties mirrors how access modifiers work in C#.
Think of the serializer/editor as being a class external to your codebase, if you want the serializer to read and write your properties you have to ensure that the access modifiers for its getter and setter allows the serializer to access them.
If you're hiding that property behind an internal
access modifier, you have to annotate it with
the attribute to ensure it is visible to the serializer.
Fields
// Read and set in the editor by default
public object obj;
// Read and set in editor with attribute
[DataMember] public internal object obj;
// Read only fields cannot be modified to point at another object, but the currently set object may be modified
public readonly object obj;
[DataMember] internal readonly object obj;
// Never
private protected/private/protected object obj;
Properties
// Read and set in the editor ...
// By default
public object obj { get; set; }
public object obj { get => x; set => x = value; }
// Forced with the attribute for 'internal' modifiers
[DataMember] public object obj { internal get; public/internal set; }
[DataMember] public object obj { internal get => x; public/internal set => x; }
// Read only
public object obj { get; }
// Read only for any non-public access modifier
public object obj { get; internal/private protected/private/protected set; }
public object obj { get => x; internal/private protected/private/protected set => x = value; }
// Read only for internal properties must be enforced through the attribute
[DataMember] internal object obj { get; }
[DataMember] internal object obj { get => x; }
// Read only, special case for get-only public properties without backing field,
//They must use the attribute to be deserialized, see the comment below
[DataMember] public object obj { get => x; }
// Read only for access modifiers more restrictive than internal, even with the attribute
[DataMember] public object obj { internal get; private protected/private/protected set; }
[DataMember] public object obj { internal get => x; private protected/private/protected set => x; }
// Never
private protected/private/protected object obj { get; set; }
private protected/private/protected object obj { get => x; set => x; }
Note
Get-only public properties without backing field (public object obj { get => x; }
) are not serialized by default as
they are, more often than not, shortcuts to values of another object or used purely as a function.
It might make more sense to change it to { get; } = new MyObject();
or { get; init; }
if you want to serialize it,
and if that doesn't work for you, feel free to add the attribute to enforce serialization.
What about init ?
The init
access modifier is seen as a public set
by the editor and serialization, it will be settable in the editor.