Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
D

DynamicData

> 前端框架
Open source

Reactive collections based on Rx.Net

1.9K stars0 likes0 views
WebsiteGitHub

About

Reactive collections based on Rx.Net

[](https://sonarcloud.io/summary/new_code?id=reactivemarbles_DynamicData) [](https://sonarcloud.io/summary/new_code?id=reactivemarbles_DynamicData) [](https://sonarcloud.io/summary/new_code?id=reactivemarbles_DynamicData) [](https://sonarcloud.io/summary/new_code?id=reactivemarbles_DynamicData) [](https://sonarcloud.io/summary/new_code?id=reactivemarbles_DynamicData)

## Dynamic Data Dynamic Data is a portable class library which brings the power of Reactive Extensions (Rx) to collections. Rx is extremely powerful but out of the box provides nothing to assist with managing collections. In most applications there is a need to update the collections dynamically. Typically a collection is loaded and after the initial load, asynchronous updates are received. The original collection will need to reflect these changes. In simple scenarios the code is simple. However, typical applications are much more complicated and may apply a filter, transform the original dto and apply a sort. Even with these simple every day operations the complexity of the code is quickly magnified. Dynamic data has been developed to remove the tedious code of dynamically maintaining collections. It has grown to become functionally very rich with at least 60 collection based operations which amongst other things enable filtering, sorting, grouping, joining different sources, transforms, binding, pagination, data virtualisation, expiration, disposal management plus more. The concept behind using dynamic data is you maintain a data source (either ```SourceCache``` or ```SourceList```), then chain together various combinations of operators to declaratively manipulate and shape the data without the need to directly manage any collection. As an example the following code will filter trades to select only live trades, creates a proxy for each live trade, and finally orders the results by most recent first. The resulting trade proxies are bound on the dispatcher thread to an observable collection. Also since the proxy is disposable ```DisposeMany()``` will ensure the proxy is disposed when no longer used. ```cs ReadOnlyObservableCollection list; var myTradeCache = new SourceCache(trade => trade.Id); var myOperation = myTradeCache.Connect() .Filter(trade=>trade.Status == TradeStatus.Live) .Transform(trade => new TradeProxy(trade)) .Sort(SortExpressionComparer.Descending(t => t.Timestamp)) .ObserveOnDispatcher() .Bind(out list) .DisposeMany() .Subscribe() ``` The magic is that as ```myTradeCache``` is maintained the target observable collection looks after itself. This is a simple example to show how using Dynamic Data's collections and operators make in-memory data management extremely easy and can reduce the size and complexity of your code base by abstracting complicated and often repetitive operations. ### Sample Projects - Sample WPF project trading project [Dynamic Trader](https://github.com/RolandPheasant/Dynamic.Trader) - Various unit tested examples of many different operators [Snippets](https://github.com/RolandPheasant/DynamicData.Snippets) - [Tail Blazer](https://github.com/RolandPheasant/TailBlazer) for tailing files ### Get in touch If you have any questions, want to get involved or would simply like to keep abreast of developments, you are welcome to join the slack community [Reactive UI Slack](https://reactiveui.net/slack). ## Table of Contents * [Dynamic Data](#dynamic-data) * [Sample Projects](#sample-projects) * [Get in touch](#get-in-touch) * [Table of Contents](#table-of-contents) * [Create Dynamic Data Collections](#create-dynamic-data-collections) * [The Observable List](#the-observable-list) * [The Observable Cache](#the-observable-cache) * [Creating Observable Change Sets](#creating-observable-change-sets) * [Connect to a Cache or List](#connect-to-a-cache-or-list) * [Create an Observable Change Set from an Rx Observable](#create-an-observable-change-set-from-an-rx-observable) * [Create an Observable Change Set from an Rx Observable with an Expiring Cache](#create-an-observable-change-set-from-an-rx-observable-with-an-expiring-cache) * [Create an Observable Change Set from an Observable Collection](#create-an-observable-change-set-from-an-observable-collection) * [Create an Observable Change Set from an Binding List](#create-an-observable-change-set-from-an-binding-list) * [Using the ObservableChangeSet static class](#using-the-observablechangeset-static-class) * [Consuming Observable Change Sets](#consuming-observable-change-sets) * [Observable list vs observable cache](#observable-list-vs-observable-cache) * [History of Dynamic Data](#history-of-dynamic-data) * [Want to know more?](#want-to-know-more) ## Create Dynamic Data Collections ### The Observable List Create an observable list like this: ```cs var myInts = new SourceList(); ``` The observable list provides the direct edit methods you would expect. For example: ```cs myInts.AddRange(Enumerable.Range(0, 10000)); myInts.Add(99999); myInts.Remove(99999); ``` The `AddRange`, `Add` and `Remove` methods above will each produce a distinct change notification. In order to increase efficiency when making multiple amendments, the list provides a means of batch editing. This is achieved using the `.Edit` method which ensures only a single change notification is produced. ```cs myInts.Edit(innerList => { innerList.Clear(); innerList.AddRange(Enumerable.Range(0, 10000)); }); ``` If ``myInts`` is to be exposed publicly it can be made read only using `.AsObservableList` ```cs IObservableList readonlyInts = myInts.AsObservableList(); ``` which hides the edit methods. The list's changes can be observed by calling `myInts.Connect()` like this: ```cs IObservable> myIntsObservable = myInts.Connect(); ``` This creates an observable change set for which there are dozens of operators. The changes are transmitted as an Rx observable, so they are fluent and composable. ### The Observable Cache Create an observable cache like this: ```cs var myCache = new SourceCache(t => key); ``` There are direct edit methods, for example ```cs myCache.Clear(); myCache.AddOrUpdate(myItems); ``` The `Clear` and `AddOrUpdate` methods above will each produce a distinct change notification. In order to increase efficiency when making multiple amendments, the cache provides a means of batch editing. This is achieved using the `.Edit` method which ensures only a single change notification is produced. ```cs myCache.Edit(innerCache => { innerCache.Clear(); innerCache.AddOrUpdate(myItems); }); ``` If `myCache` is to be exposed publicly it can be made read only using `.AsObservableCache` ```cs IObservableCache readonlyCache = myCache.AsObservableCache(); ``` which hides the edit methods. The cache is observed by calling `myCache.Connect()` like this: ```cs IObservable> myCacheObservable = myCache.Connect(); ``` This creates an observable change set for which there are dozens of operators. The changes are transmitted as an Rx observable, so they are fluent and composable. ## Creating Observable Change Sets As stated in the introduction of this document, Dynamic Data is based on the concept of creating and manipulating observable change sets. The primary method of creating observable change sets is to connect to instances of `ISourceCache` and `ISourceList`. There are alternative methods to produce observables change sets however, depending on the data source. ### Connect to a Cache or List Calling `Connect()` on a `ISourceList` or `ISourceCache` will produce an observable change set. ```cs var myObservableChangeSet = myDynamicDataSource.Connect(); ``` ### Create an Observable Change Set from an Rx Observable Given either of the following observables: ```cs IObservable myObservable; IObservable> myObservable; ``` an observable change set can be created like by calling `.ToObservableChangeSet` like this: ```cs var myObservableChangeSet = myObservable.ToObservableChangeSet(t=> t.key); ``` ### Create an Observable Change Set from an Rx Observable with an Expiring Cache The problem with the example above is that the internal backing cache of the observable change set will grow in size forever. To counter this behavior, there are overloads of `.ToObservableChangeSet` where a size limitation or expiry time can be specified for the internal cache. To create a time expiring cache, call `.ToObservableChangeSet` and specify the expiry time using the expireAfter argument: ```cs var myConnection = myObservable.ToObservableChangeSet(t=> t.key, expireAfter: item => TimeSpan.FromHours(1)); ``` To create a size limited cache, call `.ToObservableChangeSet` and specify the size limit using the limitSizeTo argument: ```cs var myConnection = myObservable.ToObservableChangeSet(t=> t.key, limitSizeTo:10000); ``` There is also an overload to specify expiration by both time and size. ### Create an Observable Change Set from an Observable Collection ```cs var myObservableCollection = new ObservableCollection(); ``` To create a cache based observable change set, call `.ToObservableChangeSet` and specify a key selector for the backing cache ```cs var myConnection = myObservableCollection.ToObservableChangeSet(t => t.Key); ``` or to create a list based observable change set call `.ToObservableChangeSet` with no arguments ```cs var myConnection = myObservableCollection.ToObservableChangeSet(); ``` This method is only recommended for simple queries which act only on the UI thread as `ObservableCollection` is not thread safe. ### Create an Observable Change Set from an Binding List ```cs var myBindingList = new BindingList(); ``` To create a cache based observable change set, call `.ToObservableChangeSet` and specify a key selector for the backing cache ```cs var myConnection = myBindingList.ToObservableChangeSet(t => t.Key); ``` or to create a list based observable change set call `.ToObservableChangeSet` with no arguments ```cs var myConnection = myBindingList.ToObservableChangeSet(); ``` This method is only recommended for simple queries which act only on the UI thread as `ObservableCollection` is not thread safe. ### Using the ObservableChangeSet static class There is also another way to create observable change sets, and that is to use the ```ObservableChangeSet``` static class. This class is a facsimile of the Rx.Net ```Observable``` static class and provides an almost identical API. An observable list can be created as follows: ```cs var myObservableList = ObservableChangeSet.Create(observableList => { //some code to load data and subscribe var loader= myService.LoadMyDataObservable().Subscribe(observableList.Add); var subscriber = myService.GetMySubscriptionsObservable().Subscribe(observableList.Add); //dispose of resources return new CompositeDisposable(loader,subscriber ); }); ``` and creating a cache is almost identical except a key has to be specified ```cs var myObservableCache = ObservableChangeSet.Create(observableCache => { //code omitted }, trade = > trade.Id); ``` There are several overloads ```ObservableChangeSet.Create``` which match the overloads which ```Observable.Create``` provides. ## Consuming Observable Change Sets The examples below illustrate the kind of things you can achieve after creating an observable change set. Now you can create an observable cache or an observable list, here are a few quick fire examples to illustrate the diverse range of things you can do. In all of these examples the resulting sequences always exactly reflect the items is the cache i.e. adds, updates

GitHub Issues· 0 open

View all on GitHub

No open issues yet, or sync has not completed.

Highlights

  • •Sample WPF project trading project Dynamic Trader
  • •Various unit tested examples of many different operators Snippets
  • •Tail Blazer for tailing files
  • •Dynamic Data
  • •Sample Projects
  • •Get in touch
  • •Table of Contents
  • •Create Dynamic Data Collections
  • •The Observable List
  • •The Observable Cache

> Tags

C#csharpdotnetdynamic-datadynamicdata

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category前端框架
PricingOpen source

> Related tools

R
React
用于构建用户界面的 JavaScript 库
V
Vue.js
渐进式 JavaScript 框架
N
Next.js
基于 React 的全栈 Web 框架