Skip to content

Settings pipeline

Vladyslav Taranov edited this page Mar 12, 2016 · 18 revisions

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.

1. Declared type

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.

2. Type override

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.

3. Member itself

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);

4. Member override

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.

Nested levels

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].

Root types

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.

Root type as a collection

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.

Clone this wiki locally