Versioning
VersioningModule<T> gives you the ability to enforce a specific version, so that when new changes
are introduced to your settings class (its scheme), a user-defined action can take place. Any of the
following VersioningResultAction values can be taken:
VersioningResultAction |
Behavior |
|---|---|
DoNothing |
Keep the old version if Json.NET parsed it successfully. Otherwise Recovery handles the load failure. |
Throw |
Throw an InvalidVersionException on loading. |
RenameAndLoadDefault |
Append the version and a collision counter to the faulty file's name, load defaults, and save them to disk. e.g. myfile.json versioned 1.0.0.5 is renamed to myfile.1.0.0.5-0.json (a second archive becomes -1, and so on). |
LoadDefault |
Load default settings without touching the existing file until the next save. |
LoadDefaultAndSave |
Load default settings and save them to disk immediately. |
Making a settings class versionable
The settings type must implement IVersionable, which contributes a Version Version { get; set; }
property:
using System;
using Nucs.JsonSettings;
using Nucs.JsonSettings.Modulation;
public class VersioningSettings : JsonSettings, IVersionable {
public override string FileName { get; set; } = "somename.jsn";
public virtual Version Version { get; set; } = new Version(1, 0, 0, 6);
public virtual string AutoProperty { get; set; } = "Hi";
public VersioningSettings() { }
public VersioningSettings(string fileName) : base(fileName) { }
}
Enforcing a version
There are two ways to specify which version to enforce.
1. Pass the version to WithVersioning:
using Nucs.JsonSettings;
using Nucs.JsonSettings.Autosave;
using Nucs.JsonSettings.Modulation;
// Load version 1.0.0.6
var settings = JsonSettings.Configure<VersioningSettings>("versioning.jsn")
.WithVersioning("1.0.0.6", VersioningResultAction.RenameAndLoadDefault)
.LoadNow()
.EnableAutosave();
settings.AutoProperty = "Hello"; //Boom! saves.
// After some development you bump the enforced version to 1.0.0.7
settings = JsonSettings.Configure<VersioningSettings>("versioning.jsn")
.WithVersioning("1.0.0.7", VersioningResultAction.RenameAndLoadDefault)
.LoadNow()
.EnableAutosave();
Console.WriteLine(settings.AutoProperty); // "Hi"
// The versions mismatch, and the action is RenameAndLoadDefault, so the old file is preserved as
// versioning.1.0.0.6.jsn and a new default versioning.jsn is written.
2. Add an [EnforcedVersion] attribute to the Version property:
[EnforcedVersion("1.0.0.0")]
public virtual Version Version { get; set; } = new Version(1, 0, 0, 0);
When dealing with inheritance / virtual overrides, the attribute of the lowest inherited class is
used. With the attribute in place you can use the WithVersioning(invalidAction) overload that takes
no explicit version.
Policy
A comparison between versions is done by the Policy, a VersioningPolicyHandler
(Func<Version, Version, bool>) passed during construction of VersioningModule<T>. If none is
given it falls back to VersioningModule.DefaultPolicy, which you can also change globally. Each
VersioningModule<T> can be assigned its own policy.
By default the versions must match exactly:
static bool DefaultEqualPolicy(Version version, Version expectedVersion) {
return expectedVersion?.Equals(version) != false;
}
Pass your own policy as the optional last argument to WithVersioning to, for example, accept any
file whose version is less than or equal to the expected one.