假设您的转换器在 int 上工作并且您的 observable 命名如下:
IObservable<IObservable<Func<int, int>>> transformerObservables = null;
IObservable<int> values = null;
我会先将 Transformers 的 Observable 转化为 Transformers 数组的 Observable,也就是
IObservable<IObservable<Func<int, int>>> -> IObservable<<Func<int, int>>[]>
首先,我们最终希望在列表中添加和删除函数,并确保删除正确的转换器,我们必须覆盖 Func<...> 上的常用比较机制。所以我们...
var transformerArrayObservable = transformerObservables
// ...attach each transformer the index of the observable it came from:
.Select((transformerObservable, index) => transformerObservable
.Select(transformer => Tuple.Create(index, transformer))
// Then, materialize the transformer sequence so we get noticed when the sequence terminates.
.Materialize()
// Now the fun part: Make a scan, resulting in an observable of tuples
// that have the previous and current transformer
.Scan(new
{
Previous = (Tuple<int, Func<int, int>>)null,
Current = (Tuple<int, Func<int, int>>)null
},
(tuple, currentTransformer) => new
{
Previous = tuple.Current,
Current = currentTransformer.HasValue
? currentTransformer.Value
: (Tuple<int, Func<int, int>>)null
}))
// Merge these and do another scan, this time adding and removing
// the transformers from a list.
.Merge()
.Scan(
new Tuple<int, Func<int, int>>[0],
(array, tuple) =>
{
//Expensive! Consider taking a dependency on immutable collections here!
var list = array.ToList();
if (tuple.Previous != null)
list.Remove(tuple.Previous);
if (tuple.Current != null)
list.Add(tuple.Current);
return list.ToArray();
})
// Extract only the actual functions
.Select(x => x.Select(y => y.Item2).ToArray())
// Finally, to make sure that values are passed even when no transformer has been observed
// start this sequence with the neutral transformation.
// IMPORTANT: You should test what happens when the first value is oberserved very quickly. There might be timing issues.
.StartWith(Scheduler.Immediate, new[] { new Func<int, int>[0]});
现在,您将需要一个 Rx 中不可用的运算符,称为 CombineVeryLatest。看看here。
var transformedValues = values
.CombineVeryLatest(transformerArrayObservable, (value, transformers) =>
{
return transformers
.Aggregate(value, (current, transformer) => transformer(current));
});
你应该完成了。我敢肯定,有一些性能要获得,但你会明白的。