我希望标题足够清晰。我正在玩弄Rx的想法并遇到一个我不确定如何制作的问题。
我有一些原始形式的事件输入,比如{ 1, 2, 3, 4, 5, 1, 2, 3, 4 }
被转换为某种新形式的输入,比如IType
。让我们说,只要观察到数字2
,计时器就会开始计时并将新的转换值(或者说,数字6
)插入到流中,除非数字5
是遇到了,在这种情况下取消了计时器。
我正在考虑构建一个从各种来源获取输入的状态机。如果我可以定时"那将是很好的。事件也是流的一部分。
代码如下,但基本上我目前仍然坚持使用Observable.Generate的一些想法(即使其看起来像Observable.Timer
,但要返回/插入新事件到输入序列)和/或可能像Observable.TakeUntil
,Observable.Create
和合并流,但我不确定是否有更好的方法,甚至如何在代码方面解决这个问题。
在代码方面,它可能是这样的
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace RxTesting
{
public interface IType
{
int OriginalInput { get; set; }
}
public class SomeEvent: IType
{
public int OriginalInput { get; set; }
}
public class TimeEvent: IType
{
public int OriginalInput { get; set; }
}
class Program
{
static void Main(string[] args)
{
//Here we should have one TimerEvent after the last "2" in the sequence.
var input = new Subject<int>();
input.Select(i => new SomeEvent { OriginalInput = i }).SomeTimerOperatorHere().Subscribe(Console.WriteLine);
input.OnNext(1);
input.OnNext(2);
input.OnNext(3);
input.OnNext(4);
input.OnNext(5);
input.OnNext(1);
input.OnNext(2);
input.OnNext(3);
input.OnNext(4);
input.Dispose();
Console.ReadKey();
}
}
}
在控制台中,应该打印一个RxTesting.TimerEvent
,因为只有一个2
,之后没有5
取消其效果。
答案 0 :(得分:1)
这应该这样做 - 我认为你的TakeUntil
想法是正确的。
我们正在过滤事件,仅包含OriginalInput
为2的事件,并将每个事件投射到值为6的单值延迟流,如果OriginalInput
为5的事件到达,则将其切断。得到的流流用SelectMany
展平。
public static IObservable<IType> SomeTimerOperatorHere(
this IObservable<SomeEvent> source)
{
var delay = TimeSpan.FromSeconds(1);
return Observable.Create<IType>(o => {
var sourcePub = source.Publish().RefCount();
return sourcePub
.Where(x => x.OriginalInput == 2)
.SelectMany(type =>
Observable.Return(new TimeEvent{ OriginalInput = 6 })
.Delay(delay)
.TakeUntil(sourcePub.Where(x => x.OriginalInput == 5))
).Subscribe(o);
});
}