Dynamic data v4 has been taken out of beta and officially released.
For source code see Dynamic Data on GitHub
For install see Dynamic Data On Nuget
Dynamic data has always had an observable cache and now after a busy 4 months development and 188 commits there is an observable list. I also could not resist throwing in some aggregation operations. These new features are outlined in this post.
Getting Started
Create an observable list like this:
var myInts= new SourceList<int>();
There are direct edit methods, for example
myInts.AddRange(Enumerable.Range(0, 10000)); myInts.Add(99999); myInts.Remove(99999);
Each amend operation will produced a change notification. A much more efficient option is to batch edit which produces a single notification.
myInts.Edit(innerList => { innerList.Clear(); innerList.AddRange(Enumerable.Range(0, 10000)); });
If SourceList
is to be exposed publicly it can be made read only
IObservableList<int> readonlyInts = myInts.AsObservableList();
which hides the edit methods.
The list changes can be observed by calling myInts.Connect()
. This creates an observable change set for which there are dozens of list specific operators. The changes are transmitted as an Rx observable so are fluent and composable.
Chain together operators
The following filters the observable list to include only odd numbers and applies a sum operation.
int total = 0; var sumOfOddNumbers = myInts.Connect() .Filter(i => i%2 == 1) .Sum(i => i) .Subscribe(result => total = result);
The result is a true observable. When values are added, replaced or removed from myInts
, the result will always reflect these changes.
Create a derived list
Any observable change set can be converted into an observable list so for example
var myOddNumberList = myInts.Connect() .Filter(i => i%2 == 1) .AsObservableList();
produces a read only observable list of odd numbers.
Dynamic data compliments Rx but since Rx does not deal with collections I have created many list specific operators to account for adds, updates, replaces and moves. There are detail below.
Observable List Operators (35 operators and counting)
The following table is a brief description of all the observable operators which can be applied to the observable list. I will use to as a basic of further detailed documentation. This will take some time but will be done in near future.
Operator | Description |
---|---|
Adapt | Injects side effects using IChangeSetAdaptor interface. |
AsObservableList | Converts an observable change set into a read only observable list / hides the edit methods of a source list. |
Bind | Ensures a specified observable collection reflects the underling data |
BufferIf | Conditional buffer which accepts a boolean observable to turn buffering on or off |
Clone | Populate an IList instance with the latest changes. |
Convert | Light weight conversion / casting of a type as specified by a value selector |
DeferUntilLoaded | Delay subscription until the source is populated with data. |
DisposeMany | Dispose each item when removed from the stream. Also disposes all items when the stream is completed. |
DistinctValues | Return a changeset of distinct values as specified by a value selector |
ExpireAfter | Time based expiry for a source list |
Filter | The semantic equivalent of Rx.Where. There is an overload to allow the predicate to be changed |
FlattenBufferResult | A changeset is already a collection and therefore becomes a nested collection when Rx buffer operatons are applied. Use this to flatten the result back to a single change set |
GroupOn | Semantic equivalent of Rx.GroupBy operator |
LimitSizeTo | Limits the size of the source cache to the specified limit, providing a notification when an item is removed due to the size limit being exceeded |
MergeMany | Dynamically merges the observable which is selected from each item in the stream, and unmerges the item when it is no longer part of the stream. |
NotEmpty | Prevents a zero count change set notification |
OnItemRemoved | Callback for each item as and when it is being removed from the stream |
Page | Applies paging to the the data source |
PopulateInto | Populates an ISourceList instance with the latest changes |
QueryWhenChanged | The latest copy of the underlying data is exposed for querying i) after each modification to the underlying data ii) upon subscription |
RefCount | Change set equivalent to Publish().RefCount(). The source is cached so long as there is at least 1 subscriber. |
SkipInitial | Defer the subscription until there is underlying data loaded and skip first set of changes |
Sort | Allow sort operators using a specified comparer. There is an overload to allow the sort to be changed |
SubscribeMany | Subscribes to each item when it is added to the stream and unsubcribes when it is removed. All items will be unsubscribed when the stream is disposed |
ToCollection | Converts the changeset into a fully formed collection. Each change in the source results in a new read only collection |
Top | Limits the size of the result set to the specified number of items |
Transform | The semantic equivalent of Rx.Select |
TransformMany | Equivalent to a select many transform |
Virtualise | Virtualises the data. Parameters are provided and changed using a virtualising controller |
WhenAnyChanged | Property changed observation of each item in the underlying collection which provides a notification when any item has changed. The notification includes the sender and value of the changed property. |
WhenAnyValueChanged | Property changed observation of each item in the underlying collection which provides a notification when any item has changed. The notification only includes the value of the changed property. |
WhereReasonsAre | Includes changes for the specified reasons only |
WhereReasonsAreNot | Excludes changes for the specified reasons |
WithKey | Applies a key to each item. This changes the change set from a list change set to a cache changeset |
This list has less operators than the observable cache but will be expanded in future releases.
Aggregation Operators
The following aggregation are also new to Dynamic Data version 4. The apply to both observable list and observable cache. With the exception of Count() which requires no parameter, the value to continually compute on is specified as a value selector Func valueSelector
Operator | Syntax |
---|---|
Count | Counts the number of items in the underlying data |
Sum | The sum of values matching the specified value selector |
Avg | The average value matching the specified value selector |
Maximum | The maximum value matching the specified value selector |
Minimum | The minimum value matching the specified value selector |
StdDev | The standard deviation of all the values matching the specified value selector |
2 thoughts on “Observable List At A Glance”