From 25782b084e3d82b03ec50d4edb61360d2ebc2325 Mon Sep 17 00:00:00 2001 From: skclusive Date: Mon, 14 Sep 2020 01:36:10 +0530 Subject: [PATCH 1/9] preview release --- Skclusive.Mobx.Observable.sln | 60 ++++++++----------- src/{Observable => }/Observable.csproj | 4 +- .../Observable.Tests.csproj | 13 ++-- 3 files changed, 36 insertions(+), 41 deletions(-) rename src/{Observable => }/Observable.csproj (79%) rename test/{Observable.Tests => }/Observable.Tests.csproj (80%) diff --git a/Skclusive.Mobx.Observable.sln b/Skclusive.Mobx.Observable.sln index 33c354c..e43c42b 100644 --- a/Skclusive.Mobx.Observable.sln +++ b/Skclusive.Mobx.Observable.sln @@ -3,13 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{97F1FFA7-2EA3-4793-B4C8-7E87B88BD6BC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Observable", "src\Observable.csproj", "{41D1F6BA-85C8-4065-880B-2117BCC00C44}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Observable", "src\Observable\Observable.csproj", "{5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{85D98476-E73E-4AC0-A3A0-BB9935E6B0C0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Observable.Tests", "test\Observable.Tests\Observable.Tests.csproj", "{D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Observable.Tests", "test\Observable.Tests.csproj", "{583F047A-E657-47E5-AC70-A73BD4BC19DC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -24,33 +20,29 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Debug|x64.ActiveCfg = Debug|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Debug|x64.Build.0 = Debug|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Debug|x86.ActiveCfg = Debug|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Debug|x86.Build.0 = Debug|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Release|Any CPU.Build.0 = Release|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Release|x64.ActiveCfg = Release|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Release|x64.Build.0 = Release|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Release|x86.ActiveCfg = Release|Any CPU - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8}.Release|x86.Build.0 = Release|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Debug|x64.ActiveCfg = Debug|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Debug|x64.Build.0 = Debug|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Debug|x86.ActiveCfg = Debug|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Debug|x86.Build.0 = Debug|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Release|Any CPU.Build.0 = Release|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Release|x64.ActiveCfg = Release|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Release|x64.Build.0 = Release|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Release|x86.ActiveCfg = Release|Any CPU - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {5F21699D-14FC-4A2D-9C05-E1FE6AE05AB8} = {97F1FFA7-2EA3-4793-B4C8-7E87B88BD6BC} - {D26EBFD2-EBD7-4A84-88DD-CE88945E8F44} = {85D98476-E73E-4AC0-A3A0-BB9935E6B0C0} + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Debug|x64.ActiveCfg = Debug|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Debug|x64.Build.0 = Debug|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Debug|x86.ActiveCfg = Debug|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Debug|x86.Build.0 = Debug|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Release|Any CPU.Build.0 = Release|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Release|x64.ActiveCfg = Release|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Release|x64.Build.0 = Release|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Release|x86.ActiveCfg = Release|Any CPU + {41D1F6BA-85C8-4065-880B-2117BCC00C44}.Release|x86.Build.0 = Release|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Debug|x64.ActiveCfg = Debug|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Debug|x64.Build.0 = Debug|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Debug|x86.ActiveCfg = Debug|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Debug|x86.Build.0 = Debug|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Release|Any CPU.Build.0 = Release|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Release|x64.ActiveCfg = Release|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Release|x64.Build.0 = Release|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Release|x86.ActiveCfg = Release|Any CPU + {583F047A-E657-47E5-AC70-A73BD4BC19DC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/src/Observable/Observable.csproj b/src/Observable.csproj similarity index 79% rename from src/Observable/Observable.csproj rename to src/Observable.csproj index 02f3a7b..445bd1d 100644 --- a/src/Observable/Observable.csproj +++ b/src/Observable.csproj @@ -1,8 +1,8 @@  - 2.0.0 + 3.0.4-preview1 $(VersionSuffix) - netstandard2.1 + net5.0 Skclusive.Mobx.Observable Skclusive.Mobx.Observable Skclusive.Mobx.Observable diff --git a/test/Observable.Tests/Observable.Tests.csproj b/test/Observable.Tests.csproj similarity index 80% rename from test/Observable.Tests/Observable.Tests.csproj rename to test/Observable.Tests.csproj index c46ea01..959cf3b 100644 --- a/test/Observable.Tests/Observable.Tests.csproj +++ b/test/Observable.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 false Skclusive.Mobx.Observable.Tests Skclusive.Mobx.Observable.Tests @@ -10,15 +10,18 @@ - - + - + - + + + + + From a0849fd41f22ee7c92291311f251fa716b6d81e7 Mon Sep 17 00:00:00 2001 From: skclusive Date: Tue, 15 Sep 2020 13:41:48 +0530 Subject: [PATCH 2/9] observable preview2 --- src/Observable.csproj | 2 +- src/Observable/Concretes/ObservableMap.cs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Observable.csproj b/src/Observable.csproj index 445bd1d..1701fa0 100644 --- a/src/Observable.csproj +++ b/src/Observable.csproj @@ -1,6 +1,6 @@  - 3.0.4-preview1 + 3.0.0-preview2 $(VersionSuffix) net5.0 Skclusive.Mobx.Observable diff --git a/src/Observable/Concretes/ObservableMap.cs b/src/Observable/Concretes/ObservableMap.cs index c19835c..91bbe25 100644 --- a/src/Observable/Concretes/ObservableMap.cs +++ b/src/Observable/Concretes/ObservableMap.cs @@ -307,11 +307,15 @@ public bool TryGetValue(TKey key, out TOut value) public IEnumerable GetValues() { + KeysAtom.ReportObserved(); + return Data.Values.Select(value => (value as IValueReader).Value); } public TIn GetValue(TKey key) { + KeysAtom.ReportObserved(); + var value = Data[key]; return (value as IValueReader).Value; From e0e7be9765ac510b11fc8d8d3e96c7142575c19e Mon Sep 17 00:00:00 2001 From: skclusive Date: Sun, 20 Sep 2020 04:18:02 +0530 Subject: [PATCH 3/9] List andMap type in changes --- src/Observable/Concretes/ObservableList.cs | 20 ++++++- src/Observable/Concretes/ObservableMap.cs | 67 +++++++++++++++++----- src/Observable/Utils/TypeUtils.cs | 9 +++ 3 files changed, 79 insertions(+), 17 deletions(-) diff --git a/src/Observable/Concretes/ObservableList.cs b/src/Observable/Concretes/ObservableList.cs index deb5c61..24a0da1 100644 --- a/src/Observable/Concretes/ObservableList.cs +++ b/src/Observable/Concretes/ObservableList.cs @@ -52,6 +52,22 @@ public static IObservableList From(IEnumerable values = null, s return list; } + public static IObservableList FromIn(IEnumerable values = null, string name = null, IManipulator manipulator = null) + { + var list = new ObservableList(name, manipulator); + + if (values != null) + { + var previous = Actions.AllowStateChangesStart(true); + + list.SpliceWithIn(0, 0, values.ToArray()); + + Actions.AllowStateChangesEnd(previous); + } + + return list; + } + public TOut this[int key] { get @@ -286,7 +302,7 @@ protected TOut[] SpliceWith(int? argIndex, int? argDeleteCount, params TOut[] ne return SpliceWithIn(argIndex, argDeleteCount, newItems.Select(newItem => Manipulator.Enhance(newItem)).ToArray()); } - private TOut[] SpliceWithIn(int? argIndex, int? argDeleteCount, params TIn[] newItems) + protected TOut[] SpliceWithIn(int? argIndex, int? argDeleteCount, params TIn[] newItems) { KeysAtom.CheckIfStateModificationsAreAllowed(); @@ -312,7 +328,7 @@ private TOut[] SpliceWithIn(int? argIndex, int? argDeleteCount, params TIn[] new var change = this.NotifyInterceptors>(ListWillChange.Splice(this, index, newItems, deleteCount)); if (change == null) { - return new TOut[] { }; + return Array.Empty(); } deleteCount = change.RemovedCount; newItems = change.Added; diff --git a/src/Observable/Concretes/ObservableMap.cs b/src/Observable/Concretes/ObservableMap.cs index 91bbe25..299cc58 100644 --- a/src/Observable/Concretes/ObservableMap.cs +++ b/src/Observable/Concretes/ObservableMap.cs @@ -25,7 +25,7 @@ public class ObservableMap : IObservableMap, I public IList>> Listeners { private set; get; } = new List>>(); - protected ObservableMap(IDictionary values, string name, IManipulator manipulator = null) + protected ObservableMap(string name, IManipulator manipulator = null) { Data = new Map>(); @@ -36,11 +36,6 @@ protected ObservableMap(IDictionary values, string name, IManipulato Manipulator = manipulator ?? Manipulator.For(); KeysAtom = new Atom($"{Name}.keys()"); - - if (values != null) - { - Merge(values); - } } public static IObservableMap From(IMap values = null, string name = null) @@ -50,7 +45,26 @@ public static IObservableMap From(IMap values = nul public static IObservableMap From(IMap values = null, string name = null, IManipulator manipulator = null) { - return new ObservableMap(values, name, manipulator); + var observableMap = new ObservableMap(name, manipulator); + + if (values != null) + { + observableMap.Merge(values); + } + + return observableMap; + } + + public static IObservableMap FromIn(IMap values = null, string name = null, IManipulator manipulator = null) + { + var observableMap = new ObservableMap(name, manipulator); + + if (values != null) + { + observableMap.MergeIn(values); + } + + return observableMap; } IDepTreeNode IDepTreeNodeFinder.FindNode(string property) @@ -173,27 +187,30 @@ public bool Has(TKey key) public ObservableMap Set(TKey key, TOut value) { - var hasKey = _Has(key); + return Set(key, Manipulator.Enhance(value)); + } - TIn newValue = Manipulator.Enhance(value); + public ObservableMap Set(TKey key, TIn value) + { + var hasKey = _Has(key); if (this.HasInterceptors()) { - var change = this.NotifyInterceptors(new MapWillChange(key, hasKey ? ChangeType.UPDATE : ChangeType.ADD, newValue, this)); + var change = this.NotifyInterceptors(new MapWillChange(key, hasKey ? ChangeType.UPDATE : ChangeType.ADD, value, this)); if (change == null) { return this; } - newValue = change.NewValue; + value = change.NewValue; } if (hasKey) { - UpdateValue(key, newValue, out TIn outValue); + UpdateValue(key, value, out TIn outValue); } else { - AddValue(key, newValue, out TIn outValue); + AddValue(key, value, out TIn outValue); } return this; @@ -254,6 +271,19 @@ public bool Remove(TKey key) return false; } + protected IObservableMap MergeIn(IDictionary values) + { + Reactions.Transaction(() => + { + foreach (var item in values) + { + Set(item.Key, item.Value); + } + }); + + return this; + } + public IObservableMap Merge(IDictionary values) { Reactions.Transaction(() => @@ -453,13 +483,20 @@ IMap IMap.Replace(IDictionary dictionary) public class ObservableMap : ObservableMap, IObservableMap { - protected ObservableMap(IDictionary values, string name, IManipulator manipulator = null) : base(values, name, manipulator) + protected ObservableMap(string name, IManipulator manipulator = null) : base(name, manipulator) { } public static new IObservableMap From(IMap values = null, string name = null) { - return new ObservableMap(values, name, null); + var observableMap = new ObservableMap(name, null); + + if (values != null) + { + observableMap.Merge(values); + } + + return observableMap; } } } diff --git a/src/Observable/Utils/TypeUtils.cs b/src/Observable/Utils/TypeUtils.cs index 4ec65a7..a927405 100644 --- a/src/Observable/Utils/TypeUtils.cs +++ b/src/Observable/Utils/TypeUtils.cs @@ -23,5 +23,14 @@ public static IDepTreeNode GetAtom(object thing, string property = null, bool no return null; } + + public static void InvalidateComputed(object thing, string property = null, bool nothrow = false) + { + var atom = GetAtom(thing, property, nothrow); + if (atom is IComputedValue computed) + { + computed.TrackAndCompute(); + } + } } } From e3038d257ff49cbd3a05e3f6013e53b1336def9d Mon Sep 17 00:00:00 2001 From: skclusive Date: Tue, 22 Sep 2020 15:38:35 +0530 Subject: [PATCH 4/9] provision to add meta object to observable object --- src/Observable/Concretes/ObservableList.cs | 14 +++++++---- src/Observable/Concretes/ObservableMap.cs | 24 +++++++++++-------- src/Observable/Concretes/ObservableObject.cs | 18 +++++++++----- src/Observable/Concretes/ObservableProxy.cs | 2 ++ src/Observable/Concretes/ObservableValue.cs | 16 ++++++++----- src/Observable/Contracts/IObservableList.cs | 2 +- src/Observable/Contracts/IObservableMap.cs | 2 +- src/Observable/Contracts/IObservableMeta.cs | 7 ++++++ src/Observable/Contracts/IObservableObject.cs | 2 +- src/Observable/Contracts/IObservableValue.cs | 2 +- 10 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 src/Observable/Contracts/IObservableMeta.cs diff --git a/src/Observable/Concretes/ObservableList.cs b/src/Observable/Concretes/ObservableList.cs index 24a0da1..9a05ab7 100644 --- a/src/Observable/Concretes/ObservableList.cs +++ b/src/Observable/Concretes/ObservableList.cs @@ -25,7 +25,9 @@ public class ObservableList : IObservableList, IDepTreeNod public IList>> Listeners { private set; get; } = new List>>(); - protected ObservableList(string name, IManipulator manipulator = null) + public object Meta { get; } + + protected ObservableList(string name, IManipulator manipulator = null, object meta = null) { Values = new List(); @@ -34,11 +36,13 @@ protected ObservableList(string name, IManipulator manipulator = null Manipulator = manipulator ?? Manipulator.For(); KeysAtom = new Atom(Name); + + Meta = meta; } - public static IObservableList From(IEnumerable values = null, string name = null, IManipulator manipulator = null) + public static IObservableList From(IEnumerable values = null, string name = null, IManipulator manipulator = null, object meta = null) { - var list = new ObservableList(name, manipulator); + var list = new ObservableList(name, manipulator, meta); if (values != null) { @@ -52,9 +56,9 @@ public static IObservableList From(IEnumerable values = null, s return list; } - public static IObservableList FromIn(IEnumerable values = null, string name = null, IManipulator manipulator = null) + public static IObservableList FromIn(IEnumerable values = null, string name = null, IManipulator manipulator = null, object meta = null) { - var list = new ObservableList(name, manipulator); + var list = new ObservableList(name, manipulator, meta); if (values != null) { diff --git a/src/Observable/Concretes/ObservableMap.cs b/src/Observable/Concretes/ObservableMap.cs index 299cc58..28562af 100644 --- a/src/Observable/Concretes/ObservableMap.cs +++ b/src/Observable/Concretes/ObservableMap.cs @@ -25,7 +25,9 @@ public class ObservableMap : IObservableMap, I public IList>> Listeners { private set; get; } = new List>>(); - protected ObservableMap(string name, IManipulator manipulator = null) + public object Meta { get; } + + protected ObservableMap(string name, IManipulator manipulator = null, object meta = null) { Data = new Map>(); @@ -36,16 +38,18 @@ protected ObservableMap(string name, IManipulator manipulator = Manipulator = manipulator ?? Manipulator.For(); KeysAtom = new Atom($"{Name}.keys()"); + + Meta = meta; } - public static IObservableMap From(IMap values = null, string name = null) + public static IObservableMap From(IMap values = null, string name = null, object meta = null) { - return From(values, name, null); + return From(values, name, null, meta); } - public static IObservableMap From(IMap values = null, string name = null, IManipulator manipulator = null) + public static IObservableMap From(IMap values = null, string name = null, IManipulator manipulator = null, object meta = null) { - var observableMap = new ObservableMap(name, manipulator); + var observableMap = new ObservableMap(name, manipulator, meta); if (values != null) { @@ -55,9 +59,9 @@ public static IObservableMap From(IMap values = nul return observableMap; } - public static IObservableMap FromIn(IMap values = null, string name = null, IManipulator manipulator = null) + public static IObservableMap FromIn(IMap values = null, string name = null, IManipulator manipulator = null, object meta = null) { - var observableMap = new ObservableMap(name, manipulator); + var observableMap = new ObservableMap(name, manipulator, meta); if (values != null) { @@ -483,13 +487,13 @@ IMap IMap.Replace(IDictionary dictionary) public class ObservableMap : ObservableMap, IObservableMap { - protected ObservableMap(string name, IManipulator manipulator = null) : base(name, manipulator) + protected ObservableMap(string name, IManipulator manipulator = null, object meta = null) : base(name, manipulator, meta) { } - public static new IObservableMap From(IMap values = null, string name = null) + public static new IObservableMap From(IMap values = null, string name = null, object meta = null) { - var observableMap = new ObservableMap(name, null); + var observableMap = new ObservableMap(name, null, meta); if (values != null) { diff --git a/src/Observable/Concretes/ObservableObject.cs b/src/Observable/Concretes/ObservableObject.cs index 42100e0..bf5cfdc 100644 --- a/src/Observable/Concretes/ObservableObject.cs +++ b/src/Observable/Concretes/ObservableObject.cs @@ -29,9 +29,11 @@ public class ObservableObject : DynamicObject, IDepTreeNodeClassifier, IDe public IList> Listeners { private set; get; } = new List>(); + public object Meta { get; } + private ObservableObject(object target, IDictionary values, Func, T> proxify, string name = null, - IManipulator manipulator = null, params Type[] otherTypes) + IManipulator manipulator = null, object meta = null, params Type[] otherTypes) { if (!typeof(T).IsInterface) { @@ -43,6 +45,8 @@ private ObservableObject(object target, IDictionary values, throw new ArgumentException($"{nameof(proxify)} should not be Null"); } + Meta = meta; + Target = target; Values = values ?? new Dictionary(); @@ -58,9 +62,11 @@ private ObservableObject(object target, IDictionary values, public ObservableObject(ObservableTypeDef typeDef, IDictionary values, Func, T> proxify, string name, - IManipulator manipulator = null, params Type[] otherTypes) + IManipulator manipulator = null, object meta = null, params Type[] otherTypes) : this((object)null, values, proxify, name, manipulator, otherTypes) { + Meta = meta; + var addObservable = ExpressionUtils.GetMethod>(x => x.AddObservableProperty("", null, null)); var isObject = typeof(W) == typeof(object); @@ -134,14 +140,14 @@ public ObservableObject(ObservableTypeDef typeDef, IDictionary From(ObservableTypeDef typeDef, Func, T> proxify, string name, IManipulator manipulator = null, params Type[] otherTypes) + public static IObservableObject From(ObservableTypeDef typeDef, Func, T> proxify, string name, IManipulator manipulator = null, object meta = null, params Type[] otherTypes) { - return new ObservableObject(typeDef, null, proxify, name, manipulator, otherTypes); + return new ObservableObject(typeDef, null, proxify, name, manipulator, meta, otherTypes); } - public static T FromAs(ObservableTypeDef typeDef, Func, T> proxify, string name, IManipulator manipulator = null, params Type[] otherTypes) + public static T FromAs(ObservableTypeDef typeDef, Func, T> proxify, string name, IManipulator manipulator = null, object meta = null, params Type[] otherTypes) { - return From(typeDef, proxify, name, manipulator, otherTypes).Proxy; + return From(typeDef, proxify, name, manipulator, meta, otherTypes).Proxy; } public override bool TrySetMember(SetMemberBinder binder, object value) diff --git a/src/Observable/Concretes/ObservableProxy.cs b/src/Observable/Concretes/ObservableProxy.cs index d9f6834..fcd9a87 100644 --- a/src/Observable/Concretes/ObservableProxy.cs +++ b/src/Observable/Concretes/ObservableProxy.cs @@ -14,6 +14,8 @@ protected ObservableProxy(IObservableObject target) public string Name => Target.Name; + public object Meta => Target.Meta; + public IList> Interceptors => Target.Interceptors; public IList> Listeners => Target.Listeners; diff --git a/src/Observable/Concretes/ObservableValue.cs b/src/Observable/Concretes/ObservableValue.cs index 781071d..897658e 100644 --- a/src/Observable/Concretes/ObservableValue.cs +++ b/src/Observable/Concretes/ObservableValue.cs @@ -5,8 +5,10 @@ namespace Skclusive.Mobx.Observable { public class ObservableValue : Atom, IObservableValue { - public ObservableValue(TIn value, string name = null, IManipulator manipulator = null) : base(name ?? $"ObservableValue@{States.NextId}") + public ObservableValue(TIn value, string name = null, IManipulator manipulator = null, object meta = null) : base(name ?? $"ObservableValue@{States.NextId}") { + Meta = meta; + Manipulator = manipulator ?? Manipulator.For(); _Value = Manipulator.Enhance(value, default(TIn), Name); @@ -22,13 +24,15 @@ public static IObservableValue From(TIn value) return From(value, null); } - public static IObservableValue From(TIn value, string name) + public static IObservableValue From(TIn value, string name, IManipulator manipulator = null, object meta = null) { - return new ObservableValue(value, name); + return new ObservableValue(value, name, manipulator, meta); } private IManipulator Manipulator { set; get; } + public object Meta { get; } + public IList, IValueWillChange>> Interceptors { private set; get; } = new List, IValueWillChange>>(); public IList>> Listeners { private set; get; } = new List>>(); @@ -175,7 +179,7 @@ public override string ToString() public class ObservableValue : ObservableValue, IObservableValue { - public ObservableValue(T value, string name = null, IManipulator manipulator = null) : base(value, name, manipulator) + public ObservableValue(T value, string name = null, IManipulator manipulator = null, object meta = null) : base(value, name, manipulator, meta) { } @@ -189,9 +193,9 @@ public ObservableValue(T value, string name = null, IManipulator manipulat return From(value, null); } - public new static IObservableValue From(T value, string name) + public new static IObservableValue From(T value, string name, IManipulator manipulator = null, object meta = null) { - return new ObservableValue(value, name); + return new ObservableValue(value, name, manipulator, meta); } } } diff --git a/src/Observable/Contracts/IObservableList.cs b/src/Observable/Contracts/IObservableList.cs index ebf8644..47fae6a 100644 --- a/src/Observable/Contracts/IObservableList.cs +++ b/src/Observable/Contracts/IObservableList.cs @@ -2,7 +2,7 @@ namespace Skclusive.Mobx.Observable { - public interface IObservableList : IList, IInterceptable>, IListenable> + public interface IObservableList : IList, IObservableMeta, IInterceptable>, IListenable> { new TOut[] Clear(); diff --git a/src/Observable/Contracts/IObservableMap.cs b/src/Observable/Contracts/IObservableMap.cs index b41b3de..3e4ba2e 100644 --- a/src/Observable/Contracts/IObservableMap.cs +++ b/src/Observable/Contracts/IObservableMap.cs @@ -2,7 +2,7 @@ namespace Skclusive.Mobx.Observable { - public interface IObservableMap : IMap, IInterceptable>, IListenable> + public interface IObservableMap : IMap, IObservableMeta, IInterceptable>, IListenable> { string Name { get; } diff --git a/src/Observable/Contracts/IObservableMeta.cs b/src/Observable/Contracts/IObservableMeta.cs new file mode 100644 index 0000000..94b48a5 --- /dev/null +++ b/src/Observable/Contracts/IObservableMeta.cs @@ -0,0 +1,7 @@ +namespace Skclusive.Mobx.Observable +{ + public interface IObservableMeta + { + object Meta { get; } + } +} diff --git a/src/Observable/Contracts/IObservableObject.cs b/src/Observable/Contracts/IObservableObject.cs index d437631..5a793fe 100644 --- a/src/Observable/Contracts/IObservableObject.cs +++ b/src/Observable/Contracts/IObservableObject.cs @@ -2,7 +2,7 @@ namespace Skclusive.Mobx.Observable { - public interface IObservableObject : IInterceptable, IListenable + public interface IObservableObject : IObservableMeta, IInterceptable, IListenable { string Name { get; } diff --git a/src/Observable/Contracts/IObservableValue.cs b/src/Observable/Contracts/IObservableValue.cs index 54db69a..ae68e1d 100644 --- a/src/Observable/Contracts/IObservableValue.cs +++ b/src/Observable/Contracts/IObservableValue.cs @@ -1,6 +1,6 @@ namespace Skclusive.Mobx.Observable { - public interface IObservableValue : IValueReader, IValueWriter + public interface IObservableValue : IValueReader, IValueWriter, IObservableMeta { string Name { get; } From 9d88907d7df3874b62ad8635b393a858ae511fda Mon Sep 17 00:00:00 2001 From: skclusive Date: Tue, 29 Sep 2020 11:39:37 +0530 Subject: [PATCH 5/9] reaction handler updated --- src/Observable/Concretes/Reaction.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Observable/Concretes/Reaction.cs b/src/Observable/Concretes/Reaction.cs index 946a2c7..015e1fc 100644 --- a/src/Observable/Concretes/Reaction.cs +++ b/src/Observable/Concretes/Reaction.cs @@ -29,7 +29,7 @@ public class Reaction : IDerivation, IReactionPublic, IDepTreeNodeClassifier private Action OnInvalidate { set; get; } - private Action ErrorHandler { set; get; } + private Action ErrorHandler { set; get; } public bool IsScheduled { private set; get; } @@ -39,7 +39,7 @@ public class Reaction : IDerivation, IReactionPublic, IDepTreeNodeClassifier public bool IsDisposed { private set; get; } - public Reaction(string name, Action onInvalidate, Action errorHandler) + public Reaction(string name, Action onInvalidate, Action errorHandler) { Name = name ?? $"Reaction@{States.NextId}"; @@ -147,7 +147,7 @@ public void Track(Func func) }); } - private void ReportExceptionInDerivation(object error) + private void ReportExceptionInDerivation(Exception error) { if (ErrorHandler != null) { From 2c21b79ac66e9d69abd8dd167d959c0fa6ce21b9 Mon Sep 17 00:00:00 2001 From: skclusive Date: Sat, 31 Oct 2020 23:59:59 +0530 Subject: [PATCH 6/9] using skclusive collection --- src/Observable.csproj | 10 +- src/Observable/Concretes/Map.cs | 56 --- src/Observable/Concretes/ObservableList.cs | 7 + src/Observable/Concretes/ObservableMap.cs | 1 + src/Observable/Concretes/OrderedDictionary.cs | 325 ------------------ src/Observable/Contracts/IMap.cs | 9 - src/Observable/Contracts/IObservableList.cs | 5 +- src/Observable/Contracts/IObservableMap.cs | 1 + .../Contracts/IOrderedDictionary.cs | 33 -- test/Observable.Tests/TestObservableMap.cs | 1 + 10 files changed, 23 insertions(+), 425 deletions(-) delete mode 100644 src/Observable/Concretes/Map.cs delete mode 100644 src/Observable/Concretes/OrderedDictionary.cs delete mode 100644 src/Observable/Contracts/IMap.cs delete mode 100644 src/Observable/Contracts/IOrderedDictionary.cs diff --git a/src/Observable.csproj b/src/Observable.csproj index 1701fa0..b8026ad 100644 --- a/src/Observable.csproj +++ b/src/Observable.csproj @@ -1,6 +1,6 @@  - 3.0.0-preview2 + 5.0.0-rc1 $(VersionSuffix) net5.0 Skclusive.Mobx.Observable @@ -9,4 +9,12 @@ Skclusive Skclusive + + + + + + diff --git a/src/Observable/Concretes/Map.cs b/src/Observable/Concretes/Map.cs deleted file mode 100644 index d7d6c11..0000000 --- a/src/Observable/Concretes/Map.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace Skclusive.Mobx.Observable -{ - public class Map : OrderedDictionary, IMap - { - public Map() - { - } - - public Map(IMap map) : base(map) - { - } - - public Map(IDictionary dictionary) : base(dictionary) - { - } - - public Map(IEqualityComparer comparer) : base(comparer) - { - } - - public Map(int capacity) : base(capacity) - { - } - - public Map(IDictionary dictionary, IEqualityComparer comparer) : base(dictionary, comparer) - { - } - - public Map(int capacity, IEqualityComparer comparer) : base(capacity, comparer) - { - } - - public IMap Replace(IDictionary dictionary) - { - var newKeys = dictionary.Keys; - var oldKeys = Keys; - - var missingKeys = oldKeys.Where(key => !newKeys.Contains(key)); - - foreach (var key in missingKeys) - { - Remove(key); - } - - foreach (var entry in dictionary) - { - this[entry.Key] = entry.Value; - } - - return this; - } - } -} diff --git a/src/Observable/Concretes/ObservableList.cs b/src/Observable/Concretes/ObservableList.cs index 9a05ab7..be0b337 100644 --- a/src/Observable/Concretes/ObservableList.cs +++ b/src/Observable/Concretes/ObservableList.cs @@ -136,6 +136,13 @@ public void Insert(int index, TOut value) Splice(index, 0, value); } + public int FindIndex(Predicate match) + { + KeysAtom.ReportObserved(); + + return Dehance(Values).ToList().FindIndex(match); + } + public void Unshift(TOut value) { Insert(0, value); diff --git a/src/Observable/Concretes/ObservableMap.cs b/src/Observable/Concretes/ObservableMap.cs index 28562af..be39de0 100644 --- a/src/Observable/Concretes/ObservableMap.cs +++ b/src/Observable/Concretes/ObservableMap.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using Skclusive.Core.Collection; namespace Skclusive.Mobx.Observable { diff --git a/src/Observable/Concretes/OrderedDictionary.cs b/src/Observable/Concretes/OrderedDictionary.cs deleted file mode 100644 index c9064c0..0000000 --- a/src/Observable/Concretes/OrderedDictionary.cs +++ /dev/null @@ -1,325 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Linq; - -namespace Skclusive.Mobx.Observable -{ - - /// - /// A dictionary that remembers the order that keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end. - /// - /// The type of keys. Musn't be - /// The type of values. - public class OrderedDictionary : IOrderedDictionary - { - /// - /// An unordered dictionary of key pairs. - /// - private readonly Dictionary fDictionary; - - /// - /// The keys of the dictionary in the exposed order. - /// - private readonly List fKeys; - - /// - /// A dictionary that remembers the order that keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end. - /// - private OrderedDictionary() - { - if (typeof(TKey) == typeof(int)) - { - throw new NotSupportedException("Integer-like type is not appropriate for keys in an ordered dictionary - accessing values by key or index would be confusing."); - } - - fKeys = new List(); - } - - /// - /// A dictionary that remembers the order that keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end. - /// - public OrderedDictionary(IDictionary dictionary = null) - : this() - { - fDictionary = new Dictionary(); - - Merge(dictionary); - } - - public OrderedDictionary(IEqualityComparer comparer) : this() - { - fDictionary = new Dictionary(comparer); - } - - public OrderedDictionary(int capacity) : this() - { - fDictionary = new Dictionary(capacity); - } - - public OrderedDictionary(int capacity, IEqualityComparer comparer) : this() - { - fDictionary = new Dictionary(capacity, comparer); - } - - public OrderedDictionary(IDictionary dictionary, IEqualityComparer comparer) : this() - { - fDictionary = new Dictionary(comparer); - - Merge(dictionary); - } - - public void Merge(IDictionary dictionary) - { - if (dictionary != null) - { - foreach (var entry in dictionary) - { - Add(entry); - } - } - } - - /// - /// The number of elements in the dictionary. - /// - public int Count - { - get - { - return fDictionary.Count; - } - } - - /// - /// This dictionary is not read only. - /// - public bool IsReadOnly - { - get - { - return false; - } - } - - /// - /// The keys of the dictionary, in order. - /// - public ICollection Keys - { - get - { - return fKeys.AsReadOnly(); - } - } - - /// - /// The values in the dictionary, in order. - /// - public ICollection Values - { - get - { - return fKeys.Select(key => fDictionary[key]).ToArray(); - } - } - - /// - /// The value at the given index. - /// - public TValue this[int index] - { - get - { - var key = fKeys[index]; - return fDictionary[key]; - } - set - { - var key = fKeys[index]; - fDictionary[key] = value; - } - } - - /// - /// The value under the given key. New entries are added at the end of the order. Updating an existing entry does not change its position. - /// - public TValue this[TKey key] - { - get - { - return fDictionary[key]; - } - set - { - if (!fDictionary.ContainsKey(key)) - { - // New entries are added at the end of the order. - fKeys.Add(key); - } - - fDictionary[key] = value; - } - } - - /// - /// Find the position of an element by key. Returns -1 if the dictionary does not contain an element with the given key. - /// - public int IndexOf(TKey key) - { - return fKeys.IndexOf(key); - } - - /// - /// Remove the element at the given index. - /// - public void RemoveAt(int index) - { - var key = fKeys[index]; - fDictionary.Remove(key); - fKeys.RemoveAt(index); - } - - /// - /// Test whether there is an element with the given key. - /// - public bool ContainsKey(TKey key) - { - return fDictionary.ContainsKey(key); - } - - /// - /// Try to get a value from the dictionary, by key. Returns false if there is no element with the given key. - /// - public bool TryGetValue(TKey key, out TValue value) - { - return fDictionary.TryGetValue(key, out value); - } - - /// - /// Insert an element at the given index. - /// - public void Insert(int index, TKey key, TValue value) - { - // Dictionary operation first, so exception thrown if key already exists. - fDictionary.Add(key, value); - fKeys.Insert(index, key); - } - - /// - /// Add an element to the dictionary. - /// - public void Add(TKey key, TValue value) - { - // Dictionary operation first, so exception thrown if key already exists. - fDictionary.Add(key, value); - fKeys.Add(key); - } - - /// - /// Add an element to the dictionary. - /// - public void Add(KeyValuePair pair) - { - Add(pair.Key, pair.Value); - } - - /// - /// Test whether the dictionary contains an element equal to that given. - /// - public bool Contains(KeyValuePair pair) - { - return fDictionary.Contains(pair); - } - - /// - /// Remove a key-value pair from the dictionary. Return true if pair was successfully removed. Otherwise, if the pair was not found, return false. - /// - public bool Remove(KeyValuePair pair) - { - if (Contains(pair)) - { - Remove(pair.Key); - return true; - } - - return false; - } - - /// - /// Remove the element with the given key key. If there is no element with the key, no exception is thrown. - /// - public bool Remove(TKey key) - { - bool wasInDictionary = fDictionary.Remove(key); - bool wasInKeys = fKeys.Remove(key); - Contract.Assume(wasInDictionary == wasInKeys); - return wasInDictionary; - } - - /// - /// Delete all elements from the dictionary. - /// - public void Clear() - { - fDictionary.Clear(); - fKeys.Clear(); - } - - /// - /// Copy the elements of the dictionary to an array, starting at at the given index. - /// - public void CopyTo(KeyValuePair[] array, int index) - { - if (array == null) - { - throw new ArgumentNullException("array"); - } - - if (index < 0) - { - throw new ArgumentOutOfRangeException("index", "Must be greater than or equal to zero."); - } - - if (index + fDictionary.Count > array.Length) - { - throw new ArgumentException("array", "Array is too small"); - } - - foreach (var pair in this) - { - array[index] = pair; - index++; - } - } - - private IEnumerable> Enumerate() - { - foreach (var key in fKeys) - { - var value = fDictionary[key]; - yield return new KeyValuePair(key, value); - } - } - - IEnumerator> IEnumerable>.GetEnumerator() - { - return Enumerate().GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return Enumerate().GetEnumerator(); - } - - /// - /// Conditions that should be true at the end of every public method. - /// - [ContractInvariantMethod] - private void ObjectInvariant() - { - Contract.Invariant(fDictionary.Count == fKeys.Count, "Unordered dictionary and ordered key list should be the same length."); - } - } -} diff --git a/src/Observable/Contracts/IMap.cs b/src/Observable/Contracts/IMap.cs deleted file mode 100644 index 8d30e00..0000000 --- a/src/Observable/Contracts/IMap.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace Skclusive.Mobx.Observable -{ - public interface IMap : IDictionary - { - IMap Replace(IDictionary dictionary); - } -} diff --git a/src/Observable/Contracts/IObservableList.cs b/src/Observable/Contracts/IObservableList.cs index 47fae6a..7cbf8e4 100644 --- a/src/Observable/Contracts/IObservableList.cs +++ b/src/Observable/Contracts/IObservableList.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Skclusive.Mobx.Observable { @@ -27,6 +28,8 @@ public interface IObservableList : IList, IObservableMeta, IInt IEnumerable GetValues(); TIn Get(int index); + + int FindIndex(Predicate match); } public interface IObservableList : IObservableList diff --git a/src/Observable/Contracts/IObservableMap.cs b/src/Observable/Contracts/IObservableMap.cs index 3e4ba2e..b4a7e98 100644 --- a/src/Observable/Contracts/IObservableMap.cs +++ b/src/Observable/Contracts/IObservableMap.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Skclusive.Core.Collection; namespace Skclusive.Mobx.Observable { diff --git a/src/Observable/Contracts/IOrderedDictionary.cs b/src/Observable/Contracts/IOrderedDictionary.cs deleted file mode 100644 index 2394ec6..0000000 --- a/src/Observable/Contracts/IOrderedDictionary.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; - -namespace Skclusive.Mobx.Observable -{ - - /// - /// A dictionary that remembers the order that keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end. - /// - /// The type of keys - /// The type of values - public interface IOrderedDictionary : IDictionary - { - /// - /// The value of the element at the given index. - /// - TValue this[int index] { get; set; } - - /// - /// Find the position of an element by key. Returns -1 if the dictionary does not contain an element with the given key. - /// - int IndexOf(TKey key); - - /// - /// Insert an element at the given index. - /// - void Insert(int index, TKey key, TValue value); - - /// - /// Remove the element at the given index. - /// - void RemoveAt(int index); - } -} diff --git a/test/Observable.Tests/TestObservableMap.cs b/test/Observable.Tests/TestObservableMap.cs index 57d4102..82ccacb 100644 --- a/test/Observable.Tests/TestObservableMap.cs +++ b/test/Observable.Tests/TestObservableMap.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Skclusive.Core.Collection; using Xunit; namespace Skclusive.Mobx.Observable.Tests From deb9ac033e38ef52919c343e1e5cbe9ede95ee9b Mon Sep 17 00:00:00 2001 From: skclusive Date: Thu, 5 Nov 2020 17:32:30 +0530 Subject: [PATCH 7/9] volatile property implemented --- src/Observable.csproj | 2 +- src/Observable/Builder/TypeBuilder.cs | 40 +++++++++++- src/Observable/Concretes/ObservableObject.cs | 68 +++++++++++++++----- src/Observable/Concretes/VolatileValue.cs | 65 +++++++++++++++++++ src/Observable/Contracts/IVolatileValue.cs | 10 +++ 5 files changed, 165 insertions(+), 20 deletions(-) create mode 100644 src/Observable/Concretes/VolatileValue.cs create mode 100644 src/Observable/Contracts/IVolatileValue.cs diff --git a/src/Observable.csproj b/src/Observable.csproj index b8026ad..fa9652c 100644 --- a/src/Observable.csproj +++ b/src/Observable.csproj @@ -1,6 +1,6 @@  - 5.0.0-rc1 + 5.0.0-rc3 $(VersionSuffix) net5.0 Skclusive.Mobx.Observable diff --git a/src/Observable/Builder/TypeBuilder.cs b/src/Observable/Builder/TypeBuilder.cs index e796590..5f1c80b 100644 --- a/src/Observable/Builder/TypeBuilder.cs +++ b/src/Observable/Builder/TypeBuilder.cs @@ -5,6 +5,15 @@ namespace Skclusive.Mobx.Observable { + public class VolatileProperty + { + public string Name { set; get; } + + public Type Type { set; get; } + + public object Default { set; get; } + } + public class ObservableProperty { public string Name { set; get; } @@ -32,11 +41,16 @@ public class ActionMethod public class ObservableTypeDef { - public ObservableTypeDef(IEnumerable observables, - IEnumerable computeds, IEnumerable actions = null) + public ObservableTypeDef( + IEnumerable observables, + IEnumerable volatiles, + IEnumerable computeds, + IEnumerable actions = null) { Observables = observables; + Volatiles = volatiles; + Computeds = computeds; Actions = actions ?? Enumerable.Empty(); @@ -44,6 +58,8 @@ public ObservableTypeDef(IEnumerable observables, public IEnumerable Observables { private set; get; } + public IEnumerable Volatiles { private set; get; } + public IEnumerable Computeds { private set; get; } public IEnumerable Actions { private set; get; } @@ -53,6 +69,8 @@ public class ObservableTypeDefBuilder { private readonly ISet ObservableProperties = new HashSet(); + private readonly ISet VolatileProperties = new HashSet(); + private readonly ISet ComputedProperties = new HashSet(); private readonly ISet ActionMethods = new HashSet(); @@ -73,6 +91,22 @@ public class ObservableTypeDefBuilder return this; } + public ObservableTypeDefBuilder Volatile(Expression> expresion, I defaultValue = default(I)) + { + var property = ExpressionUtils.GetPropertySymbol(expresion); + + VolatileProperties.Add(new VolatileProperty + { + Name = property, + + Default = defaultValue, + + Type = typeof(I) + }); + + return this; + } + public ObservableTypeDefBuilder Computed(Expression> expresion, Func compute) { var property = ExpressionUtils.GetPropertySymbol(expresion); @@ -163,7 +197,7 @@ public ObservableTypeDefBuilder Action(Expression> public ObservableTypeDef Build() { - return new ObservableTypeDef(ObservableProperties, ComputedProperties, ActionMethods); + return new ObservableTypeDef(ObservableProperties, VolatileProperties, ComputedProperties, ActionMethods); } } } diff --git a/src/Observable/Concretes/ObservableObject.cs b/src/Observable/Concretes/ObservableObject.cs index bf5cfdc..bf6e15d 100644 --- a/src/Observable/Concretes/ObservableObject.cs +++ b/src/Observable/Concretes/ObservableObject.cs @@ -17,7 +17,7 @@ public class ObservableObject : DynamicObject, IDepTreeNodeClassifier, IDe private IDictionary> PendingKeys { set; get; } - private IDictionary Values { set; get; } + private IDictionary Values { set; get; } public string Name { private set; get; } @@ -31,7 +31,8 @@ public class ObservableObject : DynamicObject, IDepTreeNodeClassifier, IDe public object Meta { get; } - private ObservableObject(object target, IDictionary values, + private ObservableObject(object target, + IDictionary values, Func, T> proxify, string name = null, IManipulator manipulator = null, object meta = null, params Type[] otherTypes) { @@ -49,7 +50,7 @@ private ObservableObject(object target, IDictionary values, Target = target; - Values = values ?? new Dictionary(); + Values = values ?? new Dictionary(); Name = name ?? $"ObservableObject@{States.NextId}"; @@ -60,14 +61,15 @@ private ObservableObject(object target, IDictionary values, Proxy = proxify(this); } - public ObservableObject(ObservableTypeDef typeDef, IDictionary values, + public ObservableObject(ObservableTypeDef typeDef, + IDictionary values, Func, T> proxify, string name, IManipulator manipulator = null, object meta = null, params Type[] otherTypes) : this((object)null, values, proxify, name, manipulator, otherTypes) { Meta = meta; - var addObservable = ExpressionUtils.GetMethod>(x => x.AddObservableProperty("", null, null)); + var addObservable = ExpressionUtils.GetMethod>(x => x.AddObservableProperty("", default, default)); var isObject = typeof(W) == typeof(object); @@ -93,6 +95,15 @@ public ObservableObject(ObservableTypeDef typeDef, IDictionary>(x => x.AddVolatileProperty(default, default)); + + foreach (var xvolatile in typeDef.Volatiles) + { + var add = addVolatile.MakeGenericMethod(xvolatile.Type); + + add.Invoke(this, new object[] { xvolatile.Name, xvolatile.Default }); + } } //public ObservableObject(T target, IDictionary values, Func, T> proxify, string name, @@ -196,9 +207,9 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, o public bool TryInvokeAction(string name, object[] args, out object result) { - if (Values.TryGetValue(name, out IObservable observable)) + if (Values.TryGetValue(name, out object vaule)) { - if (observable is IObservableAction action) + if (vaule is IObservableAction action) { result = action.Execute(args); @@ -238,16 +249,21 @@ public object Get(string key) return null; } - var observable = Values[key]; + var value = Values[key]; - if (observable is IComputedValue computed) + if (value is IComputedValue computed) { return computed.Value; } - if (observable is IObservableValue value) + if (value is IObservableValue observable) { - return value.Value; + return observable.Value; + } + + if (value is IValueReader reader) + { + return reader.Value; } return null; @@ -262,13 +278,20 @@ public bool TryWrite(string key, object value, out object newValue) return false; } - var observable = Values[key]; + var _value = Values[key]; - if (observable is IComputedValue computed) + if (_value is IComputedValue computed) { throw new InvalidOperationException($"Property {key} is computed value {computed.ToString()} and can not be updated"); } + if (_value is IVolatileValue writer) + { + (writer as IValueWriter).Value = newValue; + + return true; + } + if (this.HasInterceptors()) { var change = this.NotifyInterceptors(new ObjectWillChange(key, ChangeType.UPDATE, value, Proxy)); @@ -281,7 +304,7 @@ public bool TryWrite(string key, object value, out object newValue) value = change.NewValue; } - if (observable is IObservableValue obsvalue) + if (_value is IObservableValue obsvalue) { var oldValue = obsvalue.Value; if (obsvalue.PrepareNewValue(oldValue, value, out object changedValue)) @@ -304,7 +327,7 @@ public bool TryWrite(string key, object value, out object newValue) public bool Has(string key) { - if (Values.TryGetValue(key, out IObservable value)) + if (Values.TryGetValue(key, out object value)) { return true; } @@ -408,6 +431,13 @@ public void AddComputedProperty

(object owner, string property, IComputedValue Values[property] = computed; } + public void AddVolatileProperty(string property, V value) + { + var xvolatile = VolatileValue.From(value); + + Values[property] = xvolatile; + } + public void AddObservableProperty

(string property, W value, IManipulator manipulator) { // assertPropertyConfigurable(target, propName) @@ -514,7 +544,13 @@ public IList Keys public class ObservableObject : ObservableObject, IObservableObject where T : class { - public ObservableObject(ObservableTypeDef typeDef, IDictionary values, Func, T> proxify, string name, IManipulator manipulator = null, params Type[] otherTypes) : base(typeDef, values, (x) => proxify(x as IObservableObject), name, null, otherTypes) + public ObservableObject(ObservableTypeDef typeDef, + IDictionary values, + Func, T> proxify, + string name, + IManipulator manipulator = null, + params Type[] otherTypes) + : base(typeDef, values, (x) => proxify(x as IObservableObject), name, null, otherTypes) { } diff --git a/src/Observable/Concretes/VolatileValue.cs b/src/Observable/Concretes/VolatileValue.cs new file mode 100644 index 0000000..a2260c8 --- /dev/null +++ b/src/Observable/Concretes/VolatileValue.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; + +namespace Skclusive.Mobx.Observable +{ + public class VolatileValue : IVolatileValue + { + public VolatileValue(T value) + { + _Value = value; + } + + public static IVolatileValue From() + { + return From(default); + } + + public static IVolatileValue From(T value) + { + return new VolatileValue(value); + } + + private object _Value { get; set; } + + object IValueReader.Value + { + get + { + return _Value; + } + } + + object IValueWriter.Value + { + set + { + if (!(value is T)) + throw new Exception($"Value is not of {typeof(T).Name}"); + + _Value = value; + } + } + + T IValueReader.Value + { + get + { + return (T)_Value; + } + } + + T IValueWriter.Value + { + set + { + _Value = value; + } + } + + public override string ToString() + { + return $"{typeof(T).Name}[${_Value}]"; + } + } +} diff --git a/src/Observable/Contracts/IVolatileValue.cs b/src/Observable/Contracts/IVolatileValue.cs new file mode 100644 index 0000000..bc64819 --- /dev/null +++ b/src/Observable/Contracts/IVolatileValue.cs @@ -0,0 +1,10 @@ +namespace Skclusive.Mobx.Observable +{ + public interface IVolatileValue : IValueReader, IValueWriter + { + } + + public interface IVolatileValue : IValueReader, IValueWriter, IVolatileValue + { + } +} From d0bdb134324f4057edd5c7cd7b2f276eca544549 Mon Sep 17 00:00:00 2001 From: skclusive Date: Tue, 10 Nov 2020 00:18:35 +0530 Subject: [PATCH 8/9] volatile value added --- src/Observable.csproj | 6 +++--- src/Observable/Concretes/VolatileValue.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Observable.csproj b/src/Observable.csproj index fa9652c..a12451f 100644 --- a/src/Observable.csproj +++ b/src/Observable.csproj @@ -1,6 +1,6 @@  - 5.0.0-rc3 + 5.0.0-rc4 $(VersionSuffix) net5.0 Skclusive.Mobx.Observable @@ -11,10 +11,10 @@ - + diff --git a/src/Observable/Concretes/VolatileValue.cs b/src/Observable/Concretes/VolatileValue.cs index a2260c8..a29ee29 100644 --- a/src/Observable/Concretes/VolatileValue.cs +++ b/src/Observable/Concretes/VolatileValue.cs @@ -34,7 +34,7 @@ object IValueWriter.Value { set { - if (!(value is T)) + if (value != null && !(value is T)) throw new Exception($"Value is not of {typeof(T).Name}"); _Value = value; From 270f56b1ded7f0d20fdccfb539b7c9ca6e90f555 Mon Sep 17 00:00:00 2001 From: skclusive Date: Tue, 10 Nov 2020 22:56:04 +0530 Subject: [PATCH 9/9] 5.0.0 --- src/Observable.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Observable.csproj b/src/Observable.csproj index a12451f..1ac99e8 100644 --- a/src/Observable.csproj +++ b/src/Observable.csproj @@ -1,6 +1,6 @@  - 5.0.0-rc4 + 5.0.0 $(VersionSuffix) net5.0 Skclusive.Mobx.Observable @@ -11,10 +11,10 @@ - +