com.fofx.observething 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +1 -1
  2. package/Runtime/CollectionIdProvider.cs +71 -71
  3. package/Runtime/CollectionIdProvider.cs.meta +1 -1
  4. package/Runtime/IObservable.cs +66 -66
  5. package/Runtime/IObservable.cs.meta +1 -1
  6. package/Runtime/Implementations/Observable.cs +29 -29
  7. package/Runtime/Implementations/Observable.cs.meta +1 -1
  8. package/Runtime/Implementations/ObservableBase.cs +172 -172
  9. package/Runtime/Implementations/ObservableBase.cs.meta +1 -1
  10. package/Runtime/Implementations/ObservableCollection.cs +140 -140
  11. package/Runtime/Implementations/ObservableCollection.cs.meta +1 -1
  12. package/Runtime/Implementations/ObservableDictionary.cs +165 -165
  13. package/Runtime/Implementations/ObservableDictionary.cs.meta +1 -1
  14. package/Runtime/Implementations/ObservableList.cs +162 -162
  15. package/Runtime/Implementations/ObservableList.cs.meta +1 -1
  16. package/Runtime/Implementations/ObservableSet.cs +136 -136
  17. package/Runtime/Implementations/ObservableSet.cs.meta +1 -1
  18. package/Runtime/Implementations/ObservableValue.cs +58 -58
  19. package/Runtime/Implementations/ObservableValue.cs.meta +1 -1
  20. package/Runtime/Observables/BatchObservable.cs +71 -71
  21. package/Runtime/Observables/BatchObservable.cs.meta +1 -1
  22. package/Runtime/Observables/CastObservable.cs +127 -127
  23. package/Runtime/Observables/CastObservable.cs.meta +1 -1
  24. package/Runtime/Observables/CombineObservable.cs +95 -95
  25. package/Runtime/Observables/CombineObservable.cs.meta +1 -1
  26. package/Runtime/Observables/CombineValueObservable.cs +318 -318
  27. package/Runtime/Observables/CombineValueObservable.cs.meta +1 -1
  28. package/Runtime/Observables/ConcatObservable.cs +74 -74
  29. package/Runtime/Observables/ConcatObservable.cs.meta +1 -1
  30. package/Runtime/Observables/ContainsObservable.cs +70 -70
  31. package/Runtime/Observables/ContainsObservable.cs.meta +1 -1
  32. package/Runtime/Observables/CountObservable.cs +29 -29
  33. package/Runtime/Observables/CountObservable.cs.meta +1 -1
  34. package/Runtime/Observables/DistinctObservable.cs +54 -54
  35. package/Runtime/Observables/DistinctObservable.cs.meta +1 -1
  36. package/Runtime/Observables/FirstObservable.cs +52 -52
  37. package/Runtime/Observables/FirstObservable.cs.meta +1 -1
  38. package/Runtime/Observables/IndexOfObservable.cs +82 -82
  39. package/Runtime/Observables/IndexOfObservable.cs.meta +1 -1
  40. package/Runtime/Observables/OperationStreamObservable.cs +193 -193
  41. package/Runtime/Observables/OperationStreamObservable.cs.meta +1 -1
  42. package/Runtime/Observables/OrderByObservable.cs +115 -116
  43. package/Runtime/Observables/OrderByObservable.cs.meta +1 -1
  44. package/Runtime/Observables/SelectCollectionObservable.cs +28 -28
  45. package/Runtime/Observables/SelectCollectionObservable.cs.meta +1 -1
  46. package/Runtime/Observables/SelectListObservable.cs +28 -28
  47. package/Runtime/Observables/SelectListObservable.cs.meta +1 -1
  48. package/Runtime/Observables/SelectManyObservable.cs +77 -77
  49. package/Runtime/Observables/SelectManyObservable.cs.meta +1 -1
  50. package/Runtime/Observables/SelectValueObservable.cs +27 -27
  51. package/Runtime/Observables/SelectValueObservable.cs.meta +1 -1
  52. package/Runtime/Observables/SkipWhileObservable.cs +31 -31
  53. package/Runtime/Observables/SkipWhileObservable.cs.meta +1 -1
  54. package/Runtime/Observables/ThenObservable.cs +208 -208
  55. package/Runtime/Observables/ThenObservable.cs.meta +1 -1
  56. package/Runtime/Observables/ToDictionaryObservable.cs +35 -35
  57. package/Runtime/Observables/ToDictionaryObservable.cs.meta +1 -1
  58. package/Runtime/Observables/TrackObservable.cs +74 -74
  59. package/Runtime/Observables/TrackObservable.cs.meta +1 -1
  60. package/Runtime/Observables/UnwrapCollectionObservable.cs +63 -63
  61. package/Runtime/Observables/UnwrapCollectionObservable.cs.meta +1 -1
  62. package/Runtime/Observables/UnwrapListObservable.cs +69 -69
  63. package/Runtime/Observables/UnwrapListObservable.cs.meta +1 -1
  64. package/Runtime/Observables/UnwrapValueObservable.cs +55 -55
  65. package/Runtime/Observables/UnwrapValueObservable.cs.meta +1 -1
  66. package/Runtime/Observables/WhereObservable.cs +84 -84
  67. package/Runtime/Observables/WhereObservable.cs.meta +1 -1
  68. package/Runtime/Observables/WithPreviousObservable.cs +36 -36
  69. package/Runtime/Observables/WithPreviousObservable.cs.meta +1 -1
  70. package/Runtime/Observables.cs +466 -466
  71. package/Runtime/Observables.meta +8 -8
  72. package/Runtime/ObservationContext.cs +125 -125
  73. package/Runtime/ObservationContext.cs.meta +1 -1
  74. package/Runtime/Observers.cs +402 -402
  75. package/Runtime/Observers.cs.meta +1 -1
  76. package/Runtime/Operators/BatchOperator.cs +70 -70
  77. package/Runtime/Operators/BatchOperator.cs.meta +1 -1
  78. package/Runtime/Operators/CollectionOperator.cs +30 -30
  79. package/Runtime/Operators/CollectionOperator.cs.meta +1 -1
  80. package/Runtime/Operators/DictionaryOperator.cs +45 -45
  81. package/Runtime/Operators/DictionaryOperator.cs.meta +1 -1
  82. package/Runtime/Operators/IInitializationOperationsProvider.cs +10 -10
  83. package/Runtime/Operators/IInitializationOperationsProvider.cs.meta +1 -1
  84. package/Runtime/Operators/ListOperator.cs +44 -44
  85. package/Runtime/Operators/ListOperator.cs.meta +1 -1
  86. package/Runtime/Operators/ObservableOperator.cs +74 -74
  87. package/Runtime/Operators/ObservableOperator.cs.meta +1 -1
  88. package/Runtime/Operators/Operator.cs +65 -65
  89. package/Runtime/Operators/Operator.cs.meta +1 -1
  90. package/Runtime/Operators/SetOperator.cs +44 -44
  91. package/Runtime/Operators/SetOperator.cs.meta +1 -1
  92. package/Runtime/Operators/ValueOperator.cs +29 -29
  93. package/Runtime/Operators/ValueOperator.cs.meta +1 -1
  94. package/Runtime/Operators.meta +8 -8
  95. package/Runtime/PriorityQueue.cs +1095 -1095
  96. package/Runtime/PriorityQueue.cs.meta +1 -1
  97. package/Tests/CollectionObservableTests.cs +738 -738
  98. package/Tests/DictionaryObservableTests.cs +84 -84
  99. package/Tests/ListObservableTests.cs +147 -147
  100. package/Tests/ObservationContextTests.cs +359 -359
  101. package/Tests/ObservationContextTests.cs.meta +1 -1
  102. package/Tests/ValueObservableTests.cs +321 -321
  103. package/package.json +24 -24
@@ -1,173 +1,173 @@
1
- using System;
2
- using System.Collections.Generic;
3
- using System.Linq;
4
-
5
- namespace ObserveThing
6
- {
7
- public interface IOperation
8
- {
9
- IObservable<IOperation> source { get; }
10
- }
11
-
12
- public abstract class ObservableBase<TObserver, TOperation> : IObservable<IOperation>, IDisposable
13
- where TObserver : IObserverBase
14
- where TOperation : IOperation
15
- {
16
- private class ObserverData : IPendingObserver, IDisposable
17
- {
18
- public IObserverBase observer { get; }
19
- public bool immediate { get; }
20
- public uint priority { get; }
21
- public bool priorityAllocated { get; }
22
- public bool disposed { get; private set; }
23
-
24
- private Queue<TOperation> _pendingOperations = new Queue<TOperation>();
25
- private Action<TOperation> _sendOperation;
26
- private Action<ObserverData> _onDispose;
27
-
28
- public ObserverData(IObserverBase observer, bool immediate, uint priority, bool priorityAllocated, Action<TOperation> sendOperation, Action<ObserverData> onDispose)
29
- {
30
- this.observer = observer;
31
- this.immediate = immediate;
32
- this.priority = priority;
33
- this.priorityAllocated = priorityAllocated;
34
-
35
- _sendOperation = sendOperation;
36
- _onDispose = onDispose;
37
- }
38
-
39
- public void EnqueuePendingOperation(TOperation operation)
40
- {
41
- _pendingOperations.Enqueue(operation);
42
- }
43
-
44
- public void SendNext()
45
- {
46
- if (_pendingOperations.Count == 0)
47
- return;
48
-
49
- try
50
- {
51
- _sendOperation(_pendingOperations.Dequeue());
52
- }
53
- catch (Exception exc)
54
- {
55
- observer.OnError(exc);
56
- }
57
- }
58
-
59
- public void Dispose()
60
- {
61
- if (disposed)
62
- return;
63
-
64
- disposed = true;
65
-
66
- _onDispose?.Invoke(this);
67
-
68
- observer.OnDispose();
69
- }
70
- }
71
-
72
- public ObservationContext context { get; protected set; }
73
- public bool disposed { get; private set; }
74
-
75
- private List<ObserverData> _observers = new List<ObserverData>();
76
-
77
- public ObservableBase(ObservationContext context)
78
- {
79
- this.context = context ?? Settings.DefaultObservationContext;
80
- }
81
-
82
- private void HandleObserverDisposed(ObserverData data)
83
- {
84
- if (disposed)
85
- return;
86
-
87
- if (!_observers.Remove(data))
88
- return;
89
-
90
- if (data.priorityAllocated)
91
- context.DeallocateObserverPriority(data.priority);
92
- }
93
-
94
- protected void EnqueuePendingOperation(TOperation operation)
95
- {
96
- if (disposed)
97
- throw new ObjectDisposedException(GetType().Name);
98
-
99
- if (_observers.Count == 0)
100
- return;
101
-
102
- foreach (var observer in _observers)
103
- {
104
- observer.EnqueuePendingOperation(operation);
105
- context.RegisterPendingObserver(observer);
106
- }
107
-
108
- context.NotifyPendingObserversIfNecessary();
109
- }
110
-
111
- protected virtual void DisposeInternal() { }
112
-
113
- public void OnError(Exception error)
114
- {
115
- foreach (var observer in _observers.OrderByDescending(x => x.immediate).ThenBy(x => x.priority))
116
- observer.observer.OnError(error);
117
- }
118
-
119
- protected abstract IEnumerable<TOperation> GetInitializationOperations();
120
-
121
- protected IDisposable AddObserver(TObserver observer, bool immediate, uint? priority)
122
- => AddObserverInternal(observer, immediate, priority, op => SendOperation(observer, op));
123
-
124
- private IDisposable AddObserverInternal(IObserverBase observer, bool immediate, uint? priority, Action<TOperation> sendOperation)
125
- {
126
- if (disposed)
127
- throw new ObjectDisposedException(GetType().Name);
128
-
129
- var observerData = new ObserverData(
130
- observer,
131
- immediate,
132
- priority ?? context.AllocateObserverPriority(),
133
- priority == null,
134
- sendOperation,
135
- HandleObserverDisposed
136
- );
137
-
138
- // do this after calling OnFirstObserverAdded so any resulting operations won't be queued (they'll be reflected in GetInitializationOperations)
139
- _observers.Add(observerData);
140
-
141
- foreach (var op in GetInitializationOperations())
142
- sendOperation(op);
143
-
144
- return observerData;
145
- }
146
-
147
- protected abstract void SendOperation(TObserver observer, TOperation operation);
148
-
149
- public virtual IDisposable Subscribe(TObserver observer, bool immediate = default, uint? priority = default)
150
- => AddObserverInternal(observer, immediate, priority, op => SendOperation(observer, op));
151
-
152
- public virtual IDisposable Subscribe(IObserver<IOperation> observer, bool immediate = default, uint? priority = default)
153
- => AddObserverInternal(observer, immediate, priority, op => observer.OnNext(op));
154
-
155
- public void Dispose()
156
- {
157
- if (disposed)
158
- return;
159
-
160
- disposed = true;
161
-
162
- foreach (var observer in _observers.OrderByDescending(x => x.immediate).ThenBy(x => x.priority))
163
- {
164
- observer.Dispose();
165
- context.DeallocateObserverPriority(observer.priority);
166
- }
167
-
168
- _observers.Clear();
169
-
170
- DisposeInternal();
171
- }
172
- }
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Linq;
4
+
5
+ namespace ObserveThing
6
+ {
7
+ public interface IOperation
8
+ {
9
+ IObservable<IOperation> source { get; }
10
+ }
11
+
12
+ public abstract class ObservableBase<TObserver, TOperation> : IObservable<IOperation>, IDisposable
13
+ where TObserver : IObserverBase
14
+ where TOperation : IOperation
15
+ {
16
+ private class ObserverData : IPendingObserver, IDisposable
17
+ {
18
+ public IObserverBase observer { get; }
19
+ public bool immediate { get; }
20
+ public uint priority { get; }
21
+ public bool priorityAllocated { get; }
22
+ public bool disposed { get; private set; }
23
+
24
+ private Queue<TOperation> _pendingOperations = new Queue<TOperation>();
25
+ private Action<TOperation> _sendOperation;
26
+ private Action<ObserverData> _onDispose;
27
+
28
+ public ObserverData(IObserverBase observer, bool immediate, uint priority, bool priorityAllocated, Action<TOperation> sendOperation, Action<ObserverData> onDispose)
29
+ {
30
+ this.observer = observer;
31
+ this.immediate = immediate;
32
+ this.priority = priority;
33
+ this.priorityAllocated = priorityAllocated;
34
+
35
+ _sendOperation = sendOperation;
36
+ _onDispose = onDispose;
37
+ }
38
+
39
+ public void EnqueuePendingOperation(TOperation operation)
40
+ {
41
+ _pendingOperations.Enqueue(operation);
42
+ }
43
+
44
+ public void SendNext()
45
+ {
46
+ if (_pendingOperations.Count == 0)
47
+ return;
48
+
49
+ try
50
+ {
51
+ _sendOperation(_pendingOperations.Dequeue());
52
+ }
53
+ catch (Exception exc)
54
+ {
55
+ observer.OnError(exc);
56
+ }
57
+ }
58
+
59
+ public void Dispose()
60
+ {
61
+ if (disposed)
62
+ return;
63
+
64
+ disposed = true;
65
+
66
+ _onDispose?.Invoke(this);
67
+
68
+ observer.OnDispose();
69
+ }
70
+ }
71
+
72
+ public ObservationContext context { get; protected set; }
73
+ public bool disposed { get; private set; }
74
+
75
+ private List<ObserverData> _observers = new List<ObserverData>();
76
+
77
+ public ObservableBase(ObservationContext context)
78
+ {
79
+ this.context = context ?? Settings.DefaultObservationContext;
80
+ }
81
+
82
+ private void HandleObserverDisposed(ObserverData data)
83
+ {
84
+ if (disposed)
85
+ return;
86
+
87
+ if (!_observers.Remove(data))
88
+ return;
89
+
90
+ if (data.priorityAllocated)
91
+ context.DeallocateObserverPriority(data.priority);
92
+ }
93
+
94
+ protected void EnqueuePendingOperation(TOperation operation)
95
+ {
96
+ if (disposed)
97
+ throw new ObjectDisposedException(GetType().Name);
98
+
99
+ if (_observers.Count == 0)
100
+ return;
101
+
102
+ foreach (var observer in _observers)
103
+ {
104
+ observer.EnqueuePendingOperation(operation);
105
+ context.RegisterPendingObserver(observer);
106
+ }
107
+
108
+ context.NotifyPendingObserversIfNecessary();
109
+ }
110
+
111
+ protected virtual void DisposeInternal() { }
112
+
113
+ public void OnError(Exception error)
114
+ {
115
+ foreach (var observer in _observers.OrderByDescending(x => x.immediate).ThenBy(x => x.priority))
116
+ observer.observer.OnError(error);
117
+ }
118
+
119
+ protected abstract IEnumerable<TOperation> GetInitializationOperations();
120
+
121
+ protected IDisposable AddObserver(TObserver observer, bool immediate, uint? priority)
122
+ => AddObserverInternal(observer, immediate, priority, op => SendOperation(observer, op));
123
+
124
+ private IDisposable AddObserverInternal(IObserverBase observer, bool immediate, uint? priority, Action<TOperation> sendOperation)
125
+ {
126
+ if (disposed)
127
+ throw new ObjectDisposedException(GetType().Name);
128
+
129
+ var observerData = new ObserverData(
130
+ observer,
131
+ immediate,
132
+ priority ?? context.AllocateObserverPriority(),
133
+ priority == null,
134
+ sendOperation,
135
+ HandleObserverDisposed
136
+ );
137
+
138
+ // do this after calling OnFirstObserverAdded so any resulting operations won't be queued (they'll be reflected in GetInitializationOperations)
139
+ _observers.Add(observerData);
140
+
141
+ foreach (var op in GetInitializationOperations())
142
+ sendOperation(op);
143
+
144
+ return observerData;
145
+ }
146
+
147
+ protected abstract void SendOperation(TObserver observer, TOperation operation);
148
+
149
+ public virtual IDisposable Subscribe(TObserver observer, bool immediate = default, uint? priority = default)
150
+ => AddObserverInternal(observer, immediate, priority, op => SendOperation(observer, op));
151
+
152
+ public virtual IDisposable Subscribe(IObserver<IOperation> observer, bool immediate = default, uint? priority = default)
153
+ => AddObserverInternal(observer, immediate, priority, op => observer.OnNext(op));
154
+
155
+ public void Dispose()
156
+ {
157
+ if (disposed)
158
+ return;
159
+
160
+ disposed = true;
161
+
162
+ foreach (var observer in _observers.OrderByDescending(x => x.immediate).ThenBy(x => x.priority))
163
+ {
164
+ observer.Dispose();
165
+ context.DeallocateObserverPriority(observer.priority);
166
+ }
167
+
168
+ _observers.Clear();
169
+
170
+ DisposeInternal();
171
+ }
172
+ }
173
173
  }
@@ -1,2 +1,2 @@
1
- fileFormatVersion: 2
1
+ fileFormatVersion: 2
2
2
  guid: 009be06d9cf6e6c4fa2d65ff88b20888
@@ -1,141 +1,141 @@
1
- using System;
2
- using System.Collections;
3
- using System.Collections.Generic;
4
- using System.Linq;
5
-
6
- namespace ObserveThing
7
- {
8
- public interface ICollectionOp : IOperation
9
- {
10
- object element { get; }
11
- uint elementId { get; }
12
- bool isRemove { get; }
13
- }
14
-
15
- public struct CollectionOp<T> : ICollectionOp
16
- {
17
- public IObservable<IOperation> source { get; set; }
18
- public T element { get; set; }
19
- public uint elementId { get; set; }
20
- public bool isRemove { get; set; }
21
-
22
- object ICollectionOp.element => element;
23
- }
24
-
25
- public class ObservableCollection<T> : ObservableBase<ICollectionObserver<T>, CollectionOp<T>>, ICollectionObservable<T>, IEnumerable<T>
26
- {
27
- IEnumerator<T> IEnumerable<T>.GetEnumerator()
28
- => _collection.Values.GetEnumerator();
29
-
30
- IEnumerator IEnumerable.GetEnumerator()
31
- => _collection.Values.GetEnumerator();
32
-
33
- public int Count => _collection.Count;
34
-
35
- private Dictionary<uint, T> _collection = new Dictionary<uint, T>();
36
-
37
- private CollectionIdProvider _idProvider;
38
-
39
- public ObservableCollection() : this(default, default(IEnumerable<T>)) { }
40
- public ObservableCollection(params T[] value) : this(default, (IEnumerable<T>)value) { }
41
- public ObservableCollection(IEnumerable<T> value) : this(default, value) { }
42
-
43
- public ObservableCollection(ObservationContext context) : this(context, default(IEnumerable<T>)) { }
44
- public ObservableCollection(ObservationContext context, params T[] value) : this(context, (IEnumerable<T>)value) { }
45
- public ObservableCollection(ObservationContext context, IEnumerable<T> value) : base(context)
46
- {
47
- _idProvider = new CollectionIdProvider(_collection.ContainsKey);
48
-
49
- if (value == null)
50
- return;
51
-
52
- foreach (var element in value)
53
- {
54
- var id = _idProvider.GetUnusedId();
55
- _collection.Add(id, element);
56
- }
57
- }
58
-
59
- public bool Contains(T element)
60
- => _collection.ContainsValue(element);
61
-
62
- public uint Add(T element)
63
- {
64
- var id = _idProvider.GetUnusedId();
65
- Add(id, element);
66
- return id;
67
- }
68
-
69
- public void Add(uint id, T element)
70
- {
71
- _collection.Add(id, element);
72
- EnqueuePendingOperation(new CollectionOp<T>() { source = this, elementId = id, element = element, isRemove = false });
73
- }
74
-
75
- public bool Remove(T element)
76
- {
77
- var id = default(uint);
78
- var found = false;
79
-
80
- foreach (var kvp in _collection)
81
- {
82
- if (!Equals(element, kvp.Value))
83
- continue;
84
-
85
- id = kvp.Key;
86
- found = true;
87
- break;
88
- }
89
-
90
- if (!found)
91
- return false;
92
-
93
- return Remove(id);
94
- }
95
-
96
- public bool Remove(uint id)
97
- {
98
- if (!_collection.TryGetValue(id, out var element))
99
- return false;
100
-
101
- _collection.Remove(id);
102
- EnqueuePendingOperation(new CollectionOp<T>() { source = this, elementId = id, element = element, isRemove = true });
103
- return true;
104
- }
105
-
106
- public void Clear()
107
- {
108
- foreach (var kvp in _collection.ToArray())
109
- {
110
- _collection.Remove(kvp.Key);
111
- EnqueuePendingOperation(new CollectionOp<T>() { source = this, elementId = kvp.Key, element = kvp.Value, isRemove = true });
112
- }
113
- }
114
-
115
- protected override IEnumerable<CollectionOp<T>> GetInitializationOperations()
116
- {
117
- foreach (var elementData in _collection)
118
- yield return new CollectionOp<T>() { source = this, element = elementData.Value, elementId = elementData.Key, isRemove = false };
119
- }
120
-
121
- protected override void SendOperation(ICollectionObserver<T> observer, CollectionOp<T> operation)
122
- {
123
- if (operation.isRemove)
124
- {
125
- observer.OnRemove(operation.elementId, operation.element);
126
- }
127
- else
128
- {
129
- observer.OnAdd(operation.elementId, operation.element);
130
- }
131
- }
132
-
133
- IDisposable ICollectionObservable.Subscribe(ICollectionObserver observer, bool immediate, uint? priority)
134
- => Subscribe(new CollectionObserver<T>(
135
- onAdd: (id, element) => observer.OnAdd(id, element),
136
- onRemove: (id, element) => observer.OnRemove(id, element),
137
- onDispose: observer.OnDispose,
138
- onError: observer.OnError
139
- ), immediate, priority);
140
- }
1
+ using System;
2
+ using System.Collections;
3
+ using System.Collections.Generic;
4
+ using System.Linq;
5
+
6
+ namespace ObserveThing
7
+ {
8
+ public interface ICollectionOp : IOperation
9
+ {
10
+ object element { get; }
11
+ uint elementId { get; }
12
+ bool isRemove { get; }
13
+ }
14
+
15
+ public struct CollectionOp<T> : ICollectionOp
16
+ {
17
+ public IObservable<IOperation> source { get; set; }
18
+ public T element { get; set; }
19
+ public uint elementId { get; set; }
20
+ public bool isRemove { get; set; }
21
+
22
+ object ICollectionOp.element => element;
23
+ }
24
+
25
+ public class ObservableCollection<T> : ObservableBase<ICollectionObserver<T>, CollectionOp<T>>, ICollectionObservable<T>, IEnumerable<T>
26
+ {
27
+ IEnumerator<T> IEnumerable<T>.GetEnumerator()
28
+ => _collection.Values.GetEnumerator();
29
+
30
+ IEnumerator IEnumerable.GetEnumerator()
31
+ => _collection.Values.GetEnumerator();
32
+
33
+ public int Count => _collection.Count;
34
+
35
+ private Dictionary<uint, T> _collection = new Dictionary<uint, T>();
36
+
37
+ private CollectionIdProvider _idProvider;
38
+
39
+ public ObservableCollection() : this(default, default(IEnumerable<T>)) { }
40
+ public ObservableCollection(params T[] value) : this(default, (IEnumerable<T>)value) { }
41
+ public ObservableCollection(IEnumerable<T> value) : this(default, value) { }
42
+
43
+ public ObservableCollection(ObservationContext context) : this(context, default(IEnumerable<T>)) { }
44
+ public ObservableCollection(ObservationContext context, params T[] value) : this(context, (IEnumerable<T>)value) { }
45
+ public ObservableCollection(ObservationContext context, IEnumerable<T> value) : base(context)
46
+ {
47
+ _idProvider = new CollectionIdProvider(_collection.ContainsKey);
48
+
49
+ if (value == null)
50
+ return;
51
+
52
+ foreach (var element in value)
53
+ {
54
+ var id = _idProvider.GetUnusedId();
55
+ _collection.Add(id, element);
56
+ }
57
+ }
58
+
59
+ public bool Contains(T element)
60
+ => _collection.ContainsValue(element);
61
+
62
+ public uint Add(T element)
63
+ {
64
+ var id = _idProvider.GetUnusedId();
65
+ Add(id, element);
66
+ return id;
67
+ }
68
+
69
+ public void Add(uint id, T element)
70
+ {
71
+ _collection.Add(id, element);
72
+ EnqueuePendingOperation(new CollectionOp<T>() { source = this, elementId = id, element = element, isRemove = false });
73
+ }
74
+
75
+ public bool Remove(T element)
76
+ {
77
+ var id = default(uint);
78
+ var found = false;
79
+
80
+ foreach (var kvp in _collection)
81
+ {
82
+ if (!Equals(element, kvp.Value))
83
+ continue;
84
+
85
+ id = kvp.Key;
86
+ found = true;
87
+ break;
88
+ }
89
+
90
+ if (!found)
91
+ return false;
92
+
93
+ return Remove(id);
94
+ }
95
+
96
+ public bool Remove(uint id)
97
+ {
98
+ if (!_collection.TryGetValue(id, out var element))
99
+ return false;
100
+
101
+ _collection.Remove(id);
102
+ EnqueuePendingOperation(new CollectionOp<T>() { source = this, elementId = id, element = element, isRemove = true });
103
+ return true;
104
+ }
105
+
106
+ public void Clear()
107
+ {
108
+ foreach (var kvp in _collection.ToArray())
109
+ {
110
+ _collection.Remove(kvp.Key);
111
+ EnqueuePendingOperation(new CollectionOp<T>() { source = this, elementId = kvp.Key, element = kvp.Value, isRemove = true });
112
+ }
113
+ }
114
+
115
+ protected override IEnumerable<CollectionOp<T>> GetInitializationOperations()
116
+ {
117
+ foreach (var elementData in _collection)
118
+ yield return new CollectionOp<T>() { source = this, element = elementData.Value, elementId = elementData.Key, isRemove = false };
119
+ }
120
+
121
+ protected override void SendOperation(ICollectionObserver<T> observer, CollectionOp<T> operation)
122
+ {
123
+ if (operation.isRemove)
124
+ {
125
+ observer.OnRemove(operation.elementId, operation.element);
126
+ }
127
+ else
128
+ {
129
+ observer.OnAdd(operation.elementId, operation.element);
130
+ }
131
+ }
132
+
133
+ IDisposable ICollectionObservable.Subscribe(ICollectionObserver observer, bool immediate, uint? priority)
134
+ => Subscribe(new CollectionObserver<T>(
135
+ onAdd: (id, element) => observer.OnAdd(id, element),
136
+ onRemove: (id, element) => observer.OnRemove(id, element),
137
+ onDispose: observer.OnDispose,
138
+ onError: observer.OnError
139
+ ), immediate, priority);
140
+ }
141
141
  }
@@ -1,2 +1,2 @@
1
- fileFormatVersion: 2
1
+ fileFormatVersion: 2
2
2
  guid: c3e96a08fdf874645a4568052903de4b