虽然我不时在我的代码中使用Observable和Rx但我仍然在“推模型”及其使用方面存在这个问题。
例如,假设我有这个简单的代码:
private readonly static List<string> numbers = new List<string>
{
"1",
"2",
"3",
"4",
"5"
};
static void Main(string[] args)
{
PrintCollection();
Console.ReadLine();
numbers.Add("6");
Console.ReadLine();
}
private static void PrintCollection()
{
IObservable<string> observable = numbers.ToObservable();
observable.Subscribe<string>(x => { Console.WriteLine(x); });
}
当程序运行时,只打印1-5但不打印6,除非我使用类似ObservableCollection的东西并挂钩“CollectionChanged”事件。然而,这让我想知道“推模型”究竟是什么。我一直认为“推模型”意味着一旦数据(colleciton)订阅了一个事件,所有新添加的数据都会订阅同一个事件。
此外,我使用Observable看到的大多数示例似乎都是WPF,视图模型驱动的implmenentation,我想知道是否有人将它用于任何后端处理,这将是一个典型的例子?
答案 0 :(得分:4)
我认为你在混淆ToObservable所做的事情 - 基本上,它说“看到这一系列的东西?我想创建一个新的流,将这些价值反馈给我。”它不会以任何有意义的方式“包装”源列表,例如监听未来的更改,更多的是时间快照 - 生成的observable是创建observable时列表的样子。
有许多方法可以模拟集合的“实时视图” - 您已经提到过:创建一个ObservableCollection并创建observable,从写入CollectionChanged事件。你也可以在这里使用一个主题,虽然它将状态的概念注入到rx的“无状态”世界。
实际上,这是一个值得强调的好处:rx流在概念上比传统的命令式/ oo编程更具“功能性”;你随着时间的推移声明了一个潜在值的流,而不是一个状态机(虽然你可以强迫它像状态机一样)...你弄清楚你想要/需要的值随着时间的推移“看”,这就是你如何声明你的流。
然而,在这样的特定情况下,声明随机变化的值流是困难的;通过其他方式(事件,投票等)可以更好地满足。
那就是说,你可以这样写:
var numbers = new List<string>
{
"1",
"2",
"3",
"4",
"5"
};
var source = new ObservableCollection<string>(numbers);
var query = Observable.Create<string>((obs) =>
{
foreach(var oldItem in source)
{
obs.OnNext(oldItem);
}
NotifyCollectionChangedEventHandler h;
h = (o, e) =>
{
Console.WriteLine("Collection changed!");
foreach(var item in e.NewItems)
{
obs.OnNext(item as string);
}
};
source.CollectionChanged += h;
return Disposable.Create (() => source.CollectionChanged -= h);
});
using(query.Subscribe(Console.WriteLine))
{
source.Add("6");
Console.ReadLine();
}
输出:
1
2
3
4
5
Collection changed!
6
答案 1 :(得分:1)
您可以在订阅之前一起使用Concat Observable:
var numbers = new List<string> { "1", "2", "3", "4", "5" }.ToObservable();
numbers = numbers.Concat(new [] { "6" }.ToObservable());
numbers.Subscribe(n => Console.WriteLine(n), ex => Console.WriteLine(ex.ToString()), () => Console.WriteLine("Completed."));
输出:
1
2
3
4
五
6
完成。
您可以使用主题并在订阅后添加项目(这是一个示例,以显示事件发生的时间/地点):
var subject = new ReplaySubject<string>();
subject.OnNext("7");
subject.Subscribe(n => Console.WriteLine(n), ex => Console.WriteLine(ex.ToString()), () => Console.WriteLine("Completed."));
subject.OnNext("8");
numbers.Subscribe(n => subject.OnNext(n));
subject.OnNext("9");
subject.OnNext("10");
输出: 7 8 1 2 3 4 五 6 9 10
您还询问是否有使用Rx进行后端处理的示例。我敢说这是主要使用的地方,但我没有任何确凿的证据支持这一点。它绝对不仅仅是WPF,还有更广泛的应用程序。它是ObservableCollection,我认为它更像是WPF,因为它用于数据绑定,而ObservableCollection不是Rx的一部分。
希望有所帮助。