public void TestDynamic2() { var x = ObservableValue <int> .From(3); var xreader = x as IValueReader <int>; var xwriter = x as IValueWriter <int>; var y = ComputedValue <int> .From(() => xreader.Value *xreader.Value); Assert.Equal(9, y.Value); var values = new List <int>(); var diposable = y.Observe(change => { values.Add(change.NewValue); }); xwriter.Value = 5; Assert.Equal(25, y.Value); Assert.Single(values); Assert.Equal(25, values[0]); }
public void TestActionModificationPickup3() { var a = ObservableValue <int> .From(1); var b = 0; var doubler = ComputedValue <int> .From(() => a.Value * 2); doubler.Observe(change => { b = doubler.Value; }, true); Assert.Equal(2, b); var action = Actions.CreateAction("action", () => { a.Value = a.Value + 1; // ha, no loop! }); action(); Assert.Equal(4, b); action(); Assert.Equal(6, b); }
public void TestDynamic() { var x = ObservableValue <int> .From(3); var xreader = x as IValueReader <int>; var xwriter = x as IValueWriter <int>; var y = ComputedValue <int> .From(() => xreader.Value); var values = new List <int>(); var diposable = y.Observe(change => { values.Add(change.NewValue); }, true); Assert.Equal(3, y.Value); xwriter.Value = 5; Assert.Equal(5, y.Value); Assert.Equal(2, values.Count); Assert.Equal(3, values[0]); Assert.Equal(5, values[1]); }
private void PreCompute() { _Path = ComputedValue <string> .From(() => { if (Parent == null) { return(""); } return($"{Parent.Path}/{Subpath.EscapeJsonPath()}"); }); _Value = ComputedValue <object> .From(() => { if (!IsAlive) { return(null); } return(Type.GetValue(this)); }); _Snapshot = ComputedValue <object> .From(() => { if (!IsAlive) { return(null); } return(Type.GetSnapshot(this, false)); }); }
public Order() { Vat = ObservableValue <double> .From(0.2); Price = ObservableValue <double> .From(10); PriceWithVat = ComputedValue <double> .From(() => (Price as IValueReader <double>).Value *(1 + (Vat as IValueReader <double>).Value)); }
public void TestAllowModificationInComputed() { var a = ObservableValue <int> .From(2); var d = Reactions.Autorun(() => { var x = a.Value; }); IComputedValue <int> c2 = null; var action = Actions.CreateAction("action", () => { Actions.AllowStateChangesInsideComputed(() => { a.Value = 3; //// a second level computed should throw Assert.Throws <CaughtException>(() => { // /Computed values are not allowed to cause side effects by changing observables that are already being observed/ var x = c2.Value; }); }); Assert.Equal(3, a.Value); Assert.Throws <Exception>(() => { // /Computed values are not allowed to cause side effects by changing observables that are already being observed/ a.Value = 4; }); }); var c = ComputedValue <int> .From(() => { action(); return(a.Value); }); c2 = ComputedValue <int> .From(() => { a.Value = 6; return(a.Value); }); var _ = c.Value; d.Dispose(); }
public void TestAutorun2() { var list = ObservableList <int> .From(new[] { 4, 2, 3 }); List <int> sorted = null; var sortedX = ComputedValue <List <int> > .From(() => { var splice = list.ToList(); splice.Sort(); return(splice); }); Reactions.Autorun((r) => { sorted = sortedX.Value; }); Assert.Equal(4, list[0]); Assert.Equal(2, list[1]); Assert.Equal(3, list[2]); Assert.Equal(2, sorted[0]); Assert.Equal(3, sorted[1]); Assert.Equal(4, sorted[2]); list.Add(1); Assert.Equal(4, list[0]); Assert.Equal(2, list[1]); Assert.Equal(3, list[2]); Assert.Equal(1, list[3]); Assert.Equal(1, sorted[0]); Assert.Equal(2, sorted[1]); Assert.Equal(3, sorted[2]); Assert.Equal(4, sorted[3]); list.Shift(); Assert.Equal(2, list[0]); Assert.Equal(3, list[1]); Assert.Equal(1, list[2]); Assert.Equal(1, sorted[0]); Assert.Equal(2, sorted[1]); Assert.Equal(3, sorted[2]); }
public void TestBatch() { var a = ObservableValue <int> .From(2); var b = ObservableValue <int> .From(3); var areader = a as IValueReader <int>; var awriter = a as IValueWriter <int>; var breader = b as IValueReader <int>; var bwriter = b as IValueWriter <int>; var c = ComputedValue <int> .From(() => areader.Value *breader.Value); var d = ComputedValue <int> .From(() => c.Value *breader.Value); var values = new List <int>(); var diposable = d.Observe(change => { values.Add(change.NewValue); }); awriter.Value = 4; bwriter.Value = 5; // Note, 60 should not happen! (that is d beign computed before c after update of b) Assert.Equal(2, values.Count); Assert.Equal(36, values[0]); Assert.Equal(100, values[1]); var x = Reactions.Transaction <int>(() => { awriter.Value = 2; bwriter.Value = 3; awriter.Value = 6; Assert.Equal(54, d.Value); return(2); }); Assert.Equal(2, x); Assert.Equal(3, values.Count); Assert.Equal(36, values[0]); Assert.Equal(100, values[1]); Assert.Equal(54, values[2]); }
public void TestComputed() { var box = ObservableValue <int> .From(3); var reader = box as IValueReader <int>; var writer = box as IValueWriter <int>; var x = ComputedValue <int> .From(() => reader.Value * 2); var y = ComputedValue <int> .From(() => reader.Value * 3); Assert.Equal(6, x.Value); Assert.Equal(9, y.Value); writer.Value = 5; Assert.Equal(10, x.Value); Assert.Equal(15, y.Value); }
internal StoredReference(StoreType type, object value, IType targetType) { Type = type; Value = value; TargetType = targetType; if (Type == StoreType.Object) { if (!value.IsStateTreeNode()) { throw new ArgumentException($"Can only store references to tree nodes, got: '{value}'"); } var node = value.GetStateTreeNode(); if (string.IsNullOrWhiteSpace(node.IdentifierAttribute)) { throw new ArgumentException("Can only store references with a defined identifier attribute."); } } _resolvedValue = ComputedValue <object> .From(() => { var identifier = Value?.ToString(); if (string.IsNullOrWhiteSpace(identifier)) { return(null); } // reference was initialized with the identifier of the target var target = Node.Root.IdentifierCache?.Resolve(TargetType, identifier); if (target == null) { throw new Exception($"Failed to resolve reference '{identifier}' to type '{TargetType.Name}' (from node: {Node.Path})"); } return(target?.Value); }); }
private void PreCompute() { _Value = ComputedValue <object> .From(() => { if (!IsAlive) { return(null); } return(Type.GetValue(this)); }); _Snapshot = ComputedValue <object> .From(() => { if (!IsAlive) { return(null); } return(Type.GetSnapshot(this, false)); }); }
public void TestTransaction() { var x1 = ObservableValue <int> .From(3); var x2 = ObservableValue <int> .From(5); var x1reader = x1 as IValueReader <int>; var x1writer = x1 as IValueWriter <int>; var x2reader = x2 as IValueReader <int>; var x2writer = x2 as IValueWriter <int>; var y = ComputedValue <int> .From(() => x1reader.Value + x2reader.Value); var values = new List <int>(); var diposable = y.Observe(change => { values.Add(change.NewValue); }, true); Assert.Equal(8, y.Value); x1writer.Value = 4; Assert.Equal(9, y.Value); Reactions.Transaction(() => { x1writer.Value = 5; x2writer.Value = 6; }); Assert.Equal(11, y.Value); Assert.Equal(3, values.Count); Assert.Equal(8, values[0]); Assert.Equal(9, values[1]); Assert.Equal(11, values[2]); }
public void TestAutorunInActionDoesNotKeepComputedAlive() { var calls = 0; var computed = ComputedValue <int> .From(() => calls ++); Action callComputedTwice = () => { var x = computed.Value; var y = computed.Value; }; Action <Action> runWithMemoizing = (fun) => { Reactions.Autorun(fun).Dispose(); }; callComputedTwice(); Assert.Equal(2, calls); runWithMemoizing(callComputedTwice); Assert.Equal(3, calls); callComputedTwice(); Assert.Equal(5, calls); runWithMemoizing(() => { Actions.RunInAction <int>("x", () => { callComputedTwice(); return(0); }); }); Assert.Equal(6, calls); callComputedTwice(); Assert.Equal(8, calls); }
public void TestModificationInComputed() { var a = ObservableValue <int> .From(2); var action = Actions.CreateAction("action", () => { a.Value = 3; }); var c = ComputedValue <object> .From(() => { action(); return(null); }); var d = Reactions.Autorun(() => { // expect not to throws var x = c.Value; }); d.Dispose(); }
public void TestModificationErrorInComputed() { var a = ObservableValue <int> .From(2); var d = Reactions.Autorun(() => { var x = a.Value; }); var action = Actions.CreateAction("action", () => { a.Value = 3; }); var c = ComputedValue <int> .From(() => { action(); return(a.Value); }); Assert.Throws <Exception>(() => { var x = c.Value; }); d.Dispose(); }
public void TestComputedAutorun() { var box = ObservableValue <int> .From(3); var reader = box as IValueReader <int>; var writer = box as IValueWriter <int>; var x = ComputedValue <int> .From(() => reader.Value * 2); var values = new List <int>(); Reactions.Autorun((reaction) => { values.Add(x.Value); }); writer.Value = 5; writer.Value = 10; Assert.Equal(3, values.Count); Assert.Equal(6, values[0]); Assert.Equal(10, values[1]); Assert.Equal(20, values[2]); }
public void TestTransactionInspection() { var a = ObservableValue <int> .From(2); var areader = a as IValueReader <int>; var awriter = a as IValueWriter <int>; var calcs = 0; var b = ComputedValue <int> .From(() => { calcs++; return(areader.Value * 2); }); // if not inspected during transaction, postpone value to end Reactions.Transaction(() => { awriter.Value = 3; Assert.Equal(6, b.Value); Assert.Equal(1, calcs); }); Assert.Equal(6, b.Value); Assert.Equal(2, calcs); // if inspected, evaluate eagerly Reactions.Transaction(() => { awriter.Value = 4; Assert.Equal(8, b.Value); Assert.Equal(3, calcs); }); Assert.Equal(8, b.Value); Assert.Equal(4, calcs); }
public void TestComputedValuesAndAction() { var calls = 0; var number = ObservableValue <int> .From(1); var squared = ComputedValue <int> .From(() => { calls++; return(number.Value *number.Value); }); var changeNumber10Times = Actions.CreateAction("changeNumber10Times", () => { var x = squared.Value; var y = squared.Value; for (int i = 0; i < 10; i++) { number.Value = number.Value + 1; } }); changeNumber10Times(); Assert.Equal(1, calls); Reactions.Autorun(r => { changeNumber10Times(); Assert.Equal(2, calls); }); Assert.Equal(2, calls); changeNumber10Times(); Assert.Equal(3, calls); }
public void TestSetup() { var list = ObservableList <int> .From(); Assert.Empty(list); list.Add(1); Assert.Single(list); Assert.Equal(1, list[0]); list[1] = 2; Assert.Equal(2, list.Length); Assert.Equal(1, list[0]); Assert.Equal(2, list[1]); var compute = ComputedValue <int> .From(() => { return(-1 + list.Aggregate(1, (acc, curr) => acc + curr)); }); Assert.Equal(3, compute.Value); list[1] = 3; Assert.Equal(2, list.Length); Assert.Equal(1, list[0]); Assert.Equal(3, list[1]); Assert.Equal(4, compute.Value); list.Splice(1, 1, 4, 5); Assert.Equal(3, list.Length); Assert.Equal(1, list[0]); Assert.Equal(4, list[1]); Assert.Equal(5, list[2]); Assert.Equal(10, compute.Value); list.Replace(new[] { 2, 4 }); Assert.Equal(2, list.Length); Assert.Equal(2, list[0]); Assert.Equal(4, list[1]); Assert.Equal(6, compute.Value); list.Splice(1, 1); Assert.Equal(1, list.Length); Assert.Equal(2, list[0]); Assert.Equal(2, compute.Value); list.Splice(0, 0, new[] { 4, 3 }); Assert.Equal(3, list.Length); Assert.Equal(4, list[0]); Assert.Equal(3, list[1]); Assert.Equal(2, list[2]); Assert.Equal(9, compute.Value); list.Clear(); Assert.Empty(list); Assert.Equal(0, compute.Value); list.Length = 4; Assert.Equal(4, list.Length); Assert.Equal(0, compute.Value); list.Replace(new[] { 1, 2, 2, 4 }); Assert.Equal(4, list.Length); Assert.Equal(9, compute.Value); list.Length = 4; Assert.Equal(4, list.Length); Assert.Equal(9, compute.Value); list.Length = 2; Assert.Equal(2, list.Length); Assert.Equal(3, compute.Value); Assert.Equal(1, list[0]); Assert.Equal(2, list[1]); list.Unshift(3); Assert.Equal(3, list.Length); Assert.Equal(6, compute.Value); Assert.Equal(3, list[0]); Assert.Equal(1, list[1]); Assert.Equal(2, list[2]); list[2] = 4; Assert.Equal(3, list.Length); Assert.Equal(8, compute.Value); Assert.Equal(3, list[0]); Assert.Equal(1, list[1]); Assert.Equal(4, list[2]); }
public bool TryGetComputedValue(string calculationConfiguration, ValueRequirement valueRequirement, out ComputedValue result) { result = null; ViewCalculationResultModel model; if (!_configurationMap.TryGetValue(calculationConfiguration, out model)) { return(false); } ISet <ComputedValue> values; if (!model.TryGetAllValues(valueRequirement.TargetSpecification, out values)) { return(false); } var computedValues = values.Where(v => valueRequirement.IsSatisfiedBy(v.Specification)); result = computedValues.FirstOrDefault(); return(result != null); }
public ViewResultEntry(string calculationConfiguration, ComputedValue computedValue) { _calculationConfiguration = calculationConfiguration; _computedValue = computedValue; }