-
Notifications
You must be signed in to change notification settings - Fork 3
Settings pipeline
Each member settings are determined from multiple layers and each of them overrides values specified in previous layers. Some layers can only be specified from code by using RuntimeTypeModel
. In examples I will use the Format
setting which is described in details here.
Can be specified with attribute:
[SerializableType(ValueFormat.Reference)]
public class Foo
{
}
Or from a code:
RuntimeTypeModel model = TypeModel.Create();
var tm = model.Add(typeof(Foo), true); // may already exist, it's ok
tm.DefaultFormat = ValueFormat.Reference;
For generics concrete types (not definitions) should be registered.
Foo
and Foo?
are different types.
Provides an override which will be applied on all model types:
RuntimeTypeModel model = TypeModel.Create();
// all types will have Compact format
model.AddTypeOverride(type => type.DefaultFormat = ValueFormat.Compact);
Overrides are invoked before finalizing type settings which happens when a type is first used for building a member serializer or when a root type serializer is being built.
Can be specified with attribute:
[SerializableMember(5, ValueFormat.Compact)]
public Foo FooMember { get; set; }
Or from a code:
RuntimeTypeModel model = TypeModel.Create();
var tm = model.Add(typeof(Foo), true); // may already exist, it's ok
tm[5].SetSettings(x => x.V.Format = ValueFormat);
Provides an override which will be applied on all model type members:
RuntimeTypeModel model = TypeModel.Create();
// all types will have Compact format
model.AddFieldOverride(type => type.SetSettings(x => x.V.Format = ValueFormat.Compact);
Overrides are invoked before finalizing member settings which happens when a container type serializer is being built.
Collection members have nested levels e.g.
public List<Bar>[] Bars { get; set; }
has levels:
Level | Type | Serializer |
---|---|---|
0 | List<Bar>[] | Array |
1 | List<Bar> | List |
2 | Bar | Type |
Each level separately uses the same pipeline as described above.
E.g. level 2 will use settings for type Bar
overridden by specified level settings on the member Bars
:
[SerializableMember(5)]
[SerializableMemberNested(2, ValueFormat.Compact)] // serialize Bar as compact
public List<Bar>[] Bars { get; set; }
Settings specified on [SerializableMember]
will apply to level 0.
Each level can be specified from a code:
tm[5].SetSettings(x => x.V.Format = ValueFormat, /* nested level: */ 2);
If you omit level
argument then level 0 will be used the same way as with [SerializableMember]
.
When you pass an instance as a root object
model.Serialize(ms, new Bar());
it will use settings specified for type with [SerializableType]
or MetaType
.
You may want to serialize a collection as a root object like
model.Serialize(ms, new List<Bar>[0]);
for nested level 2 settings specified on the Bar
type will be used. If you want to override them for List<Bar>
case you can do it from a code like:
model.Add(typeof(List<Bar>[]), true)
.SetNestedSettingsWhenRoot(x => x.V.Format = ValueFormat.Compact, 2);
Note that not nested root collections may use Auxiliary mode.