可观察对象的一般用法



尽管我在代码中不时地使用Observable和Rx,但我仍然有这个关于"push model"及其使用的问题。

例如,假设我有这样一个简单的代码:
  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"事件。然而,这让我想知道"推送模式"到底是什么。我一直认为"推送模型"意味着一旦数据(集合)订阅了一个事件,所有新添加到该集合的数据也将订阅同一个事件。

另外,我看到的大多数使用Observable的例子似乎都是WPF,视图模型驱动的实现,我想知道是否有人将它用于任何后端处理,典型的例子是什么?

我想你是混淆了ToObservable做什么-基本上,它说"看到这组东西吗?我想创造一种新的流,将这些价值反馈给我。"它不会以任何有意义的方式"包装"源列表,比如监听未来的变化,它更像是一个及时的快照——生成的可观察对象是可观察对象创建时列表的样子。

有很多方法可以为一个集合的"实时视图"建模——你提到过的一种:创建一个ObservableCollection,并通过写入CollectionChanged事件来创建可观察对象。您也可以在这里使用Subject,尽管它将状态的概念注入到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

您可以在订阅之前将可观察对象连接在一起:

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."));

输出:123.456完成。

你可以使用Subject并在Subscription后面添加条目(这里有一个示例来显示事情发生的时间/地点):

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");

输出:78123.456910

您还询问是否有使用Rx进行后端处理的示例。我敢说这是它的主要用途,但我没有任何确凿的证据来支持这一点。它绝对不仅仅是WPF,还有更广泛的应用。它是ObservableCollection,这更多的是WPF的事情,我相信,因为它用于数据绑定和ObservableCollection不是Rx的一部分。

希望对你有帮助。

相关内容

  • 没有找到相关文章

最新更新