2

いくつかの異なる「タイプ」の着信イベントがあり、それらをプロパティとして公開された異なる IObservables にディスパッチしたいのですが、基になる UDP に複数回サブスクライブする必要はありません。

public IObservable<TimeEvent> TimeEventChannel { get; private set; }
public IObservable<SpaceEvent> SpaceEventChannel { get; private set; }

Subject<TimeEvent> _TimeSubject = new Subject<TimeEvent>();
Subject<SpaceEvent> _SpaceSubject = new Subject<SpaceEvent>();

public EventDispatcher(IChannelListener listener)
{
    TimeEventChannel = _TimeSubject;
    SpaceEventChannel = _SpaceSubject;
    listener.Data.Subscribe(SwitchEvent);
}

private void SwitchEvent(AbstractEvent e)
{
    switch(e.EventType)
    {
        case EEventType.Time: _TimeSubject.OnNext(e as TimeEvent); break;
        case EEventType.Space: _SpaceSubject.OnNext(e as SpaceEvent); break;
    }
}

(listener.DataIObservable<AbstractEvent>) です。

私が抱えている問題は、これを分離して(UDPに接続せずに)テストする方法を考え出そうとしていることです

var spaceEvent = new SpaceEvent();
var udpSubject = new Subject<AbstractEvent>();
var mock = new Mock<IChannelListener>();
mock.SetupGet(listener => listener.Data).Returns(udpSubject);
var dispatcher = new EventDispatcher(mock.Object);

subject.OnNext(spaceEvent);
var result = dispatcher.SpaceEventChannel.SingleOrDefault();

現状では、テストは最後の行でブロックされています。これは、動作方法について根本的に理解していない何かがあるためだと確信していSubjectます。

質問: 何が間違っていると思いますか? この特定のユースケースをテストするにはどうすればよいですか? Dispatcher も逆方向に実装していますか?


念のため、これはChannelListener現在の実際の外観です。

public ChannelListener(UdpClient udpClient, FrameInterpreter frameInterpreter)
{
    Data = Observable.Defer(() => 
    {
        IPEndPoint ep = null;
        return Observable.FromAsyncPattern<byte[]>(
                    udpClient.BeginReceive,
                    i => udpClient.EndReceive(i, ref ep)
                )()
                .Select(bytes => frameInterpreter.ParseFrame(bytes));
    });
}

public IObservable<AbstractEvent> Data { get; private set; }
4

2 に答える 2

2

問題は次の行にあると思います。

subject.OnNext(spaceEvent);
var result = dispatcher.SpaceEventChannel.SingleOrDefault();

それを次のように置き換えてみてください:

AbstractEvent result = null;
dispatcher.SpaceEventChannels.Subscribe(e => result = e);
subject.OnNext(spaceEvent);
// ...

問題は、subject.OnNext を呼び出すと、*すぐに*「パイプライン」を介して実行されることです。したがって、次の行の SingleOrDefault は実際にテキストをロックします。値が「到着」しないためです。

于 2012-05-09T07:35:16.740 に答える
0

あなたが抱えている主な問題は単純です。この行:

listener.Data.Subscribe(SwitchEvent);

を返しますIDisposable。これはすぐに範囲外になり、破棄されます。したがって、SwitchEvent決して発火しません。クラスIDisposableのインスタンス変数にそれを保持するだけです。EventDispatcher

private IDisposable _subscription;

public EventDispatcher(IChannelListener listener)
{
    TimeEventChannel = _TimeSubject;
    SpaceEventChannel = _SpaceSubject;
    _subscription = listener.Data.Subscribe(SwitchEvent);
}

また、それが本当に必要なすべてである場合ではなく、EventDispatcherを受け入れるように変更することを真剣に検討します。これにより、テストがどれほど簡単になるか想像できます。IObservable<AbstractEvent>IChannelListener

于 2012-05-09T07:00:51.217 に答える