我正在尝试生成一系列事件,这些事件由文件名组成,这些文件名是目录中的现有文件。
效果很好。代码如下:
Observable.Generate(
ExistingFiles(path, filter),
Condition(),
Iterate(),
CreateFileChangedEvent()
)
private static Func<List<string>.Enumerator, FileChangedEvent> CreateFileChangedEvent()
{
return enumerator => new FileChangedEvent(enumerator.Current, @"Existing");
}
private static Func<List<string>.Enumerator, List<string>.Enumerator> Iterate()
{
return enumerator =>
{
enumerator.MoveNext();
return enumerator;
};
}
private static List<string>.Enumerator ExistingFiles(string path, string filter)
{
List<string>.Enumerator files =
Directory.GetFiles(path, filter)
.ToList()
.GetEnumerator();
// Advance the enumerator to the first result
files.MoveNext();
return files;
}
private static Func<List<string>.Enumerator, bool> Condition()
{
return enumerator => enumerator.Current != null;
}
}
我想将这个observable包装在另一个可以按时间触发文件枚举的observable中。 我所有的重复/重播尝试都不会触发文件搜索并生成以前的事件,这不是我想要的。
提前致谢。
编辑1 : 好吧,使用ToObservable()
可以简化代码Directory.GetFiles(path, filter)
.ToObservable()
.Select(s => new FileChangedEvent(s, @"Existing"))
答案 0 :(得分:-1)
如果您希望在interval上运行文件搜索,可以执行以下操作:
Observable.Interval(TimeSpan.FromSeconds(2))
.Select(_ =>
Directory.GetFiles(path, filter)
.ToObservable()
.Select(s => new FileChangedEvent(s, @"Existing"))
)
.SelectMany(_ => _)
.Subscribe(onNewFileChangedEvent => {
Console.WriteLine(onNewFileChangedEvent.ToString());
});
但这会产生相同的“现有”文件更改事件,您需要在将它们发送到订阅之前进行重复删除(我猜?)。您可以使用Buffer operator来创建两组文件的差异并仅发出这些文件。
原始流返回Interval
的计时器事件。在每个事件中,我们都会返回FileChangedEvents
的新流。
t1--t2--t3
\ \ \
\ \ ---t3{evt1,evt2,evt3}
\ ---t{evt1,evt2,evt3}
---t1{evt1,evt2,evt3}
因为我们希望将这些信息融合到我们的订阅者可以使用的一个流中,所以我们必须合并这些结果。输入SelectMany()
,将投影和展平组合成一个步骤。因为我们不是。我们对projection
的{{1}}属性不感兴趣,我们指出我们将对selectMany
强调语法所指示的项目(通过惯例)不执行任何操作。
_ => _
本质上是标识Merge()
的语义等价物(有重载执行控制并发等有趣的事情)。连续生成要合并的序列肯定没有问题。这是original implementation