反应性的扩展.CRUD应用程序示例
本文关键字:应用程序 CRUD 扩展 | 更新日期: 2023-09-27 18:09:27
我刚刚开始掌握响应式扩展,但仍然没有"啊哈"的时刻,当一切似乎都到位的时刻。因此,我需要一些帮助,并且想知道响应式扩展在一个简单的CRUD程序中可能扮演什么样的角色。
有没有人有RX扩展如何帮助他们的CRUD应用程序的例子?正如你所想象的,我正在用c#编写一个CRUD应用程序……任何例子都可以接受,这是张贴的,这样我就可以思考RX如何适合我正在做的编程类型。
也许你可以列出一个编程任务是如何从RX中受益的,以及在使用RX之前该任务是如何完成的。
我做过这种事情,效果很好:
public interface IStorage : IDisposable
{
IObservable<int> GetOperationsCount(IScheduler scheduler);
IObservable<Node> FetchNodes(IObservable<NodeId> nodeIds, IScheduler scheduler);
IObservable<Node> StoreNodes(IObservable<Node> nodes, IScheduler scheduler);
}
它允许我在后台线程上执行取值和存储,并在UI线程上很容易地返回值给我。
对StoreNodes
的每次调用也建立一个事务,我可以从返回的可观察对象中获得任何错误。
我还使用GetOperationsCount
可观察对象向用户显示挂起操作的数量,等等。
我对Rx的个人经验让我想把它用于任何异步的事情——事件、开始/结束调用、异步、任务、线程等。它使所有内容都适合一个模型,并且可以节省大量代码。
如果你做静态CRUD(获得一个窗口/对话框与创建,读取,更新,写入,无论什么),那么我想它可能只会帮助你的UI。例如,也许你想要某些输入的自动完成功能。或者您必须查询服务以获取要显示的其他信息。那么RX可以帮你做到这一点。它将隐藏许多与异步相关的困难,并为您提供可读的、可以轻松阅读和快速执行的声明式表达式。从这个意义上讲,它就像LINQ一样,只是UI/async
一个典型的CRUD应用程序有一些UI (winform, WPF等)和一个数据存储来获取数据并显示在UI中。这两个组件(UI和数据存储)之间的数据流可以使用Rx建模。
使用Rx我们可以连接两个组件(UI和数据存储),例如:UI可以为Create, Update和Delete公开3个可观察对象(例如:在构造函数中传递给数据存储)。例如:Submit按钮事件可以被映射成Create可观察值,Update和delete也可以。所以基本上数据存储需要订阅这3个可观察对象,而不需要关心数据是如何生成的(这也有助于在UT中轻松创建伪可观察对象)。
Read将是一个简单的读取数据存储的方法,因为它是关于按需提取数据。
所以基本上Rx作为一个抽象来组成这两个组件。
也许我错了,考虑这两个答案。微软倾向于把他们的业务分成很多层,因为他们在这方面有兴趣。
CRUD是物理实现-创建-读取-…但UI似乎是合乎逻辑的-在上下文中-为用户…
有时候你需要有一个层——业务层——来控制进出RDMS的流。在我看来,这太复杂了。在金融业务中,"更新"或"删除"操作是用新的时间戳复制当前行。这使得清洁手术变得困难——至少在物理上……最重要的是,您可能会认为CRUD只是事务的一部分——在运行中创建"一个逻辑工作单元",直到一切正常——那么您应该执行COMMIT。
希望这将帮助…
CRUD应用程序将具有某种搜索功能。你可以用"输入并等待搜索"来实现一个文本框搜索,就像我最近在博客上写的演示一样:
http://blog.andrei.rinea.ro/2013/06/01/bing-it-on-reactive-extensions-story-code-and-slides/基本上使用油门和其他响应式扩展,你可以创建一个快速搜索功能。
Rx非常适合集合。现在,我无法想象使用一种没有LINQ功能的语言。
最近,Rx也是一样的,主要是因为LINQ使用了Rx: DynamicData
ReadOnlyObservableCollection<TradeProxy> list;
var myTradeCache = new SourceCache<Trade, long>(trade => trade.Id);
var myOperation = myTradeCache.Connect()
.Filter(trade=>trade.Status == TradeStatus.Live)
.Transform(trade => new TradeProxy(trade))
.Sort(SortExpressionComparer<TradeProxy>.Descending(t => t.Timestamp))
.ObserveOnDispatcher()
.Bind(out list)
.DisposeMany()
.Subscribe()
基本上,您可以创建类似LINQ的查询,在任何更改后动态刷新自己-源列表中的新项(只需DTO就足够了!),一些属性更改,来自其他地方的信号(作为可观察对象传递)等。
您想要显示带有标志的实体数量吗?一个班轮。
您想根据用户选择的属性轻松显示动态组吗?一个班轮。
要分页吗?3行:P
还有一个叫做ReactiveUI的MVVM框架——它为你提供了一个ReactiveCommand和一些更多的技巧。
其中包括绑定框架和基于lambdas的转换器,在视图中对VM中发生的非常具体的事情做出反应的能力,管理视图模型的激活(如初始命令执行,但不是在构造函数中)。
您希望登录按钮仅在用户和密码不为空时才启用?
Login = ReactiveCommand.CreateFromTask(async () => { /* your async implementation, it can return a value! */},
this.WhenAnyValue(x => x.Username, x => x.Password, (user, psw) => !string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(psw)); // define when the command can execute by providing IObservable<bool>
Login.Where(x => x == true) // only successful logins, ==true for clarity
.InvokeCommand(DisplayMainScreen); // or something
In view你可以这样做:
Login.Where(x => !x).Subscribe(_ =>{ // if login failed, set focus on password and select all text so user can just retype the password
PasswordBox.SelectAllText(); // can't remember exact methods, but you get the idea
PasswordBox.SetFocus();
});
对于你来说,创建"当某事时,做这个"这样的功能变得很自然