在Reactive Extensions中合并Observable?

时间:2015-03-28 04:00:08

标签: c# system.reactive

刚刚学习RX并希望制作一个迭代文件系统的程序。以下是我提出的有效方法:

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();
        }
    }
}

(注意通过再次调用GetFiles并订阅来使用递归)

虽然它起作用但看起来非常笨拙,但我无法想到我应该使用像Concat这样的东西来组合序列而不是仅仅将它们冒回来。

此外,我想将Foreach更改为Parallel.ForEach,但我不确定使用RX会产生什么后果。我似乎无法找到很多文档。

有关如何使用RX更好地编写此内容的提示吗?

2 个答案:

答案 0 :(得分:2)

要解决这样的问题,首先编写函数的LINQ版本会很有帮助。例如:

    static IEnumerable<string> GetFiles(string folder, string filePattern)
    {
        return Directory.GetFiles(folder, filePattern)
            .Concat(Directory.GetDirectories(folder).SelectMany(f => GetFilesEnumerable(f, filePattern)));
    }

然后只需将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)));
    }

答案 1 :(得分:0)

事实证明,基于我对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();
        }
    }
}

疯狂现在真的很简单。需要一个新的RX问题。