private static void _distinct_internal <T>(this IOperationController controller, object key, Func <T, T, IOperation> generateMergedOperation) where T : class, IMergeableOperation { var operations = controller.Operations.ToList(); var mergeable = operations .OfType <T>() .Where(x => x.MergeJudge.GetMergeKey() == key) .ToArray(); var first = mergeable.FirstOrDefault(); var last = mergeable.LastOrDefault(); if (first is null || last is null) { return; } var lastIndex = 0; foreach (var operation in mergeable) { lastIndex = operations.IndexOf(operation); operations.RemoveAt(lastIndex); } var newOperation = generateMergedOperation(first, last); operations.Insert(lastIndex, newOperation); controller.Flush(); operations.ForEach(x => controller.Push(x)); }
public static IOperation PushTo(this IOperation _this, IOperationController controller) { if (_this is IMergeableOperation mergeableOperation) { _this = mergeableOperation.Merge(controller); } return(controller.Push(_this)); }
public static IOperation ExecuteAndCombineTop(this IOperation _this, IOperationController controller) { if (controller.Operations.Any()) { var prev = controller.Pop(); _this.RollForward(); var newOperation = prev.CombineOperations(_this).ToCompositeOperation(); newOperation.Messaage = _this.Messaage; return(controller.Push(newOperation)); } return(controller.Execute(_this)); }
public static IDisposable BindPropertyChanged <T>(this IOperationController controller, INotifyPropertyChanged owner, string propertyName, bool autoMerge = true) { var prevValue = FastReflection.GetProperty <T>(owner, propertyName); var callFromOperation = false; owner.PropertyChanged += PropertyChanged; return(new Disposer(() => owner.PropertyChanged -= PropertyChanged)); // local function void PropertyChanged(object sender, PropertyChangedEventArgs args) { if (callFromOperation) { return; } if (args.PropertyName == propertyName) { callFromOperation = true; T newValue = FastReflection.GetProperty <T>(owner, propertyName); var operation = owner .GenerateAutoMergeOperation(propertyName, newValue, prevValue, $"{sender.GetHashCode()}.{propertyName}", Operation.DefaultMergeSpan); if (autoMerge) { operation = operation.Merge(controller); } operation .AddPreEvent(() => callFromOperation = true) .AddPostEvent(() => callFromOperation = false); prevValue = newValue; controller.Push(operation); callFromOperation = false; } } }