[英]Merging Observables in Reactive Extensions?
Just learning RX and wanted to make a program that iterated the file system. 刚学习RX并想制作一个迭代文件系统的程序。 Here is what I came up with that works:
这是我想出的方法:
using System;
using System.IO;
using System.Reactive.Disposables;
using System.Reactive.Linq;
namespace ConsoleApplication8
{
internal class Program
{
private static IObservable<string> GetFiles(string folder, string filePattern)
{
return Observable.Create<string>(
o =>
{
var files = Directory.GetFiles(folder, filePattern);
foreach (var file in files)
{
o.OnNext(file);
}
var folders = Directory.GetDirectories(folder);
foreach (var f in folders)
{
var x = GetFiles(f, filePattern);
x.Subscribe(p => { o.OnNext(p); });
}
o.OnCompleted();
return Disposable.Empty;
});
}
private static void Main(string[] args)
{
var o = GetFiles(@"d:\temp", "*.*");
o.Subscribe(p => { Console.WriteLine(p); });
Console.Read();
}
}
}
(Note the use of recursion by calling GetFiles again and subscribing) (请注意,通过再次调用GetFiles并订阅来使用递归)
While it works it seems very clumsy, I can't help thinking that I should be using something like Concat to combine the sequences instead of just bubbling them back up. 虽然它看起来很笨拙,但我不禁想到我应该使用像Concat这样的东西来组合序列,而不是仅仅将它们冒泡备份。
Also I would like to change that Foreach to a Parallel.ForEach but I'm unsure the ramifications this would have using RX. 我也想将Foreach更改为Parallel.ForEach,但是我不确定使用RX会带来的后果。 I can't seem to find much for documentation.
我似乎找不到太多的文档资料。
Any tips on how to write this better using RX? 关于如何使用RX更好地编写此代码的任何提示?
To solve a problem like this, it can help to write a LINQ version of the function first. 为了解决这样的问题,可以首先编写该函数的LINQ版本。 eg:
例如:
static IEnumerable<string> GetFiles(string folder, string filePattern)
{
return Directory.GetFiles(folder, filePattern)
.Concat(Directory.GetDirectories(folder).SelectMany(f => GetFilesEnumerable(f, filePattern)));
}
Then just change the IEnumerables to IObservables: 然后只需将IEnumerables更改为IObservables:
static IObservable<string> GetFiles(string folder, string filePattern)
{
return Directory.GetFiles(folder, filePattern).ToObservable()
.Concat(Directory.GetDirectories(folder).ToObservable().SelectMany(f => GetFilesEnumerable(f, filePattern)));
}
Turns out, based on my discovery of SearchOption.AllDirectories (why in all my years have I never noticed this) it can be boiled down into two real lines of code: 事实证明,根据我对SearchOption.AllDirectories的发现(为什么我多年来从未注意到这一点),可以将其简化为两行代码:
using System;
using System.IO;
using System.Reactive.Linq;
namespace ConsoleApplication8
{
internal class Program
{
private static void Main(string[] args)
{
var o = Directory.GetFiles(@"e:\code", "*.*", SearchOption.AllDirectories).ToObservable();
o.Subscribe(f => Console.WriteLine(f));
Console.Read();
}
}
}
Crazy how simple it really is now. 疯狂,现在真的如此简单。 Need a new RX problem to play with.
需要一个新的RX问题来玩。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.