75 lines
2.1 KiB
C#
75 lines
2.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace FlowScope.Save
|
|
{
|
|
public sealed class SaveMigrationRegistry
|
|
{
|
|
private readonly Dictionary<MigrationKey, ISaveMigration> _migrations = new();
|
|
|
|
public void Register(ISaveMigration migration)
|
|
{
|
|
if (migration == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(migration));
|
|
}
|
|
|
|
_migrations[new MigrationKey(migration.Key, migration.FromVersion)] = migration;
|
|
}
|
|
|
|
public string Migrate(
|
|
string key,
|
|
int fromVersion,
|
|
int currentVersion,
|
|
string json)
|
|
{
|
|
var current = fromVersion;
|
|
var payload = json;
|
|
while (current < currentVersion)
|
|
{
|
|
if (!_migrations.TryGetValue(new MigrationKey(key, current), out var migration) ||
|
|
migration.ToVersion != current + 1)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Missing save migration for key '{key}' from version {current}.");
|
|
}
|
|
|
|
payload = migration.Migrate(payload);
|
|
current = migration.ToVersion;
|
|
}
|
|
|
|
return payload;
|
|
}
|
|
|
|
private readonly struct MigrationKey : IEquatable<MigrationKey>
|
|
{
|
|
private readonly string _key;
|
|
private readonly int _fromVersion;
|
|
|
|
public MigrationKey(string key, int fromVersion)
|
|
{
|
|
_key = key ?? string.Empty;
|
|
_fromVersion = fromVersion;
|
|
}
|
|
|
|
public bool Equals(MigrationKey other)
|
|
{
|
|
return _key == other._key && _fromVersion == other._fromVersion;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return obj is MigrationKey other && Equals(other);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
unchecked
|
|
{
|
|
return ((_key != null ? _key.GetHashCode() : 0) * 397) ^ _fromVersion;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|