简体   繁体   English

在可扩展中合并可观察变量?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM