private void ActualizeToLastState() { var newDynamicTree = diffApplier.ToDynamic(worldTreeService.EditingWorld); // todo: initialize this previousDynamicTree = previousDynamicTree ?? newDynamicTree; var diff = diffBuilder.BuildDiffs(previousDynamicTree, newDynamicTree, diffIdentityComparer); if (!diff.IsEmpty) { diffApplier.ApplyDiff(worldTreeService.EditingWorld, diff, TrwDiffDirection.Backward); } }
public override void ApplyDiff(ITrwSerializationDiffApplier applier, TObj target, ITrwDiff diff, TrwDiffDirection direction) { if (typeof(TObj).IsValueType) { base.ApplyDiff(applier, target, diff, direction); return; } if (!(diff is MutateObjectTrwDiff odiff)) { throw new ArgumentException("Diff of type MutateObjectTrwDiff is expected."); } if (odiff.AddedProperties.Any() || odiff.RemovedProperties.Any()) { throw new ArgumentException("Diffs with added or removed properties are not applicable."); } foreach (var kvp in odiff.DiffedProperties) { if (!TryGetProp(target, kvp.First, out var prop)) { continue; } var forward = direction == TrwDiffDirection.Forward; switch (kvp.Second) { case ReplaceValueTrwDiff replaceDiff: var newValue = (TValue)applier.FromDynamic(GetPropType(prop), forward ? replaceDiff.NewValue : replaceDiff.OldValue); SetPropValue(target, target, prop, newValue); break; default: var value = GetPropValue(target, prop); applier.ApplyDiff(value, kvp.Second, direction); break; } } }
public override void ApplyDiff(ITrwSerializationDiffApplier applier, TArray target, ITrwDiff diff, TrwDiffDirection direction) { if (!(diff is MutateArrayTrwDiff adiff)) { throw new ArgumentException("Diff of type MutateArrayTrwDiff expected."); } TItem[] result; switch (direction) { case TrwDiffDirection.Forward: { result = new TItem[GetCount(target) + adiff.AddedItems.Count - adiff.RemovedItems.Count]; foreach (var pair in adiff.AddedItems) { result[pair.First] = (TItem)applier.FromDynamic(typeof(TItem), pair.Second); } foreach (var pair in adiff.MovedItems) { result[pair.Second] = GetItem(target, pair.First); } foreach (var pair in adiff.DiffedItems) { var item = GetItem(target, pair.First.First); applier.ApplyDiff(item, pair.Second, direction); result[pair.First.Second] = item; } break; } case TrwDiffDirection.Backward: { result = new TItem[GetCount(target) - adiff.AddedItems.Count + adiff.RemovedItems.Count]; foreach (var pair in adiff.RemovedItems) { result[pair.First] = (TItem)applier.FromDynamic(typeof(TItem), pair.Second); } foreach (var pair in adiff.MovedItems) { result[pair.First] = GetItem(target, pair.Second); } foreach (var pair in adiff.DiffedItems) { var item = GetItem(target, pair.First.Second); applier.ApplyDiff(item, pair.Second, direction); result[pair.First.First] = item; } break; } default: throw new ArgumentOutOfRangeException(nameof(direction), direction, null); } foreach (var i in adiff.UnaffectedItems) { result[i] = GetItem(target, i); } for (var i = 0; i < result.Length; i++) { var item = result[i]; var targetIndex = typeof(TItem).IsValueType ? typeof(IEquatable <TItem>).IsAssignableFrom(typeof(TItem)) ? EnumerateItems(target).IndexOf(x => ((IEquatable <TItem>)x).Equals(item)) : EnumerateItems(target).IndexOf(x => Equals(x, item)) : EnumerateItems(target).IndexOf(x => ReferenceEquals(x, item)); if (targetIndex.HasValue) { if (targetIndex.Value == i) { continue; } RemoveAt(target, targetIndex.Value); Insert(target, i, item); } else { Insert(target, i, item); } } for (var i = GetCount(target) - 1; i >= result.Length; i--) { RemoveAt(target, i); } }
public void Apply() { applier.ApplyDiff(world, diff, TrwDiffDirection.Forward); }