Rx框架的实用扩展方法

Rx框架之旅始于一个个人小项目。如今,几乎每天都在使用Rx框架,这要归功于一个让生活变得更轻松的小型个人框架。所以,今天没有长篇大论的文章,毕竟今天是周五,只是列举一下最喜欢的一些反应式框架扩展方法。这篇文章可以看作是之前那篇关于一些实用类的文章的续集。

如何订阅PropertyChanged事件

当对某个视图模型的属性变更感兴趣时,经常需要编写如下的意大利面条代码:

public void UpdateUser(User user) { user.PropertyChanged += user_PropertyChanged; NameChanged(); } void user_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Name") NameChanged(); } private void NameChanged() { // Do wonderful stuff }

将其替换为:

user .ItemPropertyChanged(u => u.Name, true) .Subscribe((args) => { // Do wonderful stuff with args.NewValue and args.OldValue });

布尔值会在订阅时直接触发订阅动作。注意,可以通过args参数获取属性的NewValue和OldValue,不再需要魔法字符串。

如何订阅CollectionChanged事件

替换旧的方式,对每个添加到可观察集合中的物品执行操作:

public void SubscribeToCollection(ObservableCollection users) { users.CollectionChanged += users_CollectionChanged; foreach (var user in users) { NewUser(user); } } void users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) foreach (User user in e.NewItems) { NewUser(user); } } private void NewUser(User user) { // Do something }

转化为响应式方式:

users .ForeachItem() .Subscribe(user => { // Do something });

如何订阅ObservableCollection中的物品

基本上,是将前面两种旧方法的意大利面条代码结合起来。

public void SubscribeToCollection(ObservableCollection users) { users.CollectionChanged += users_CollectionChanged; foreach (var user in users) { NewUser(user); } } void users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) foreach (User user in e.NewItems) { NewUser(user); } if (e.OldItems != null) { foreach (User user in e.OldItems) { user.PropertyChanged -= UserChanged; } } } private void NewUser(User user) { user.PropertyChanged += UserChanged; } void UserChanged(object sender, PropertyChangedEventArgs e) { // Do wonderful stuff when one user changes }

转化为干净的版本:

users .ObserveEachItem(u => u.ItemPropertyChanged()) .Subscribe(args => { User user = args.Sender; // Do wonderful stuff when one user changes });

弱事件监听器

是否尝试过以弱引用的方式订阅一个对象,以便垃圾回收器能够正确地回收不再引用的监听器?

一种解决方案是阅读MSDN页面并使用WeakEventManager。抱歉,懒得为阅读。另一种解决方案是使用ObserveWeakly方法:

var subscription = user.ItemPropertyChanged() .ObserveWeakly() .Subscribe(args => { User u = args.Sender; // User changed do what you want... }); subscription = null; // OMG forgot to Dispose the subscription !!! memory leak !1! GC.Collect(); user.AssertSubscribers(0); // Just kidding

订阅依赖属性变更

订阅依赖属性的代码并不简单,如下代码片段所示:

TextBox box = new TextBox(); DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(TextBox.BackgroundProperty, typeof(TextBox)); if (dpd != null) { dpd.AddValueChanged(box, (sender, args) => { // Do wonderful stuff when the background changed }); }

但不用担心,现在可以这样做:

TextBox box = new TextBox(); box.DependencyPropertyChanged<Brush>(TextBox.BackgroundProperty) .Subscribe(args => { Brush brush = args.NewValue; });

同步两个ObservableCollection

相信不止一次遇到过这样的情况,例如想要一个ObservableCollection<String>,它动态地列出ObservableCollection<User>中所有女孩的名字。

ObservableCollection<String> GirlsNames = new ObservableCollection<String>(); public void SubscribeToCollection(ObservableCollection<User> users) { users.CollectionChanged += users_CollectionChanged; foreach (var user in users) { NewUser(user); } } void users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) foreach (User user in e.NewItems) { NewUser(user); } if (e.OldItems != null) { foreach (User user in e.OldItems) { GirlsNames.Remove(user.Name); } } } private void NewUser(User user) { if (user.Gender = Gender.Girl) GirlsNames.Add(user.Name); } users.MapToCollection(GirlsNames, u => u.Name, u => u.Gender == Gender.Girl);
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485