Das Hauptproblem, mit dem Sie konfrontiert sind, ist, dass Sie eine Quelle für Ihre Observable benötigen. Im Allgemeinen können Sie Observables aus einer Vielzahl von Quellen erstellen, z. B. Ereignisse, Delegaten, Aufgaben, viele der beobachtbaren Erweiterungen (wie .Interval
oder .Generate
) und Themen.
In Ihrem Fall müssen Sie eine Quelle haben, die Sie Code haben können, extern zu Ihrer Observable, Push-Werte zu. In diesem Fall ist ein Thema völlig in Ordnung, aber Sie könnten auch einen Delegierten verwenden.
Wenn Sie ein Thema verwenden, ist Ihr Code in Ordnung. Der einzige Nachteil ist, dass Sie updateSubject.OnCompleted
aufrufen und das Observable beenden können.
Wenn Sie einen Delegaten verwenden möchten, dann könnte Ihr Code wie folgt aussehen:
private Action<GameTime> updateGameTime = null;
public void Initialize()
{
component = new Component();
Observable
.FromEvent<GameTime>(a => updateGameTime += a, a => updateGameTime -= a)
.Subscribe((gameTime) => component.Update(gameTime));
}
public void Update(GameTime gameTime)
{
updateGameTime(gameTime);
}
Auf diese Weise das einzige, was Sie mit updateGameTime
tun kann, ist in einer neuen GameTime
passieren - man kann nicht „aus Versehen "Beenden Sie die Sequenz.
Jetzt ist das ganze Problem mit der Verwendung von Themen im Vergleich zu Observable.Create
einer der Staat. In deinem Code brauchst du den Status, also ist ein Thema in Ordnung. Im Allgemeinen, und wann immer es möglich ist, ist es ratsam, den Zustand einzukapseln - und das ist es, was Observable.Create
für Sie tut.
Nehmen Sie dieses Beispiel:
var i = -1;
var query =
Observable
.Range(0, 10).Select(x =>
{
i = -i * 2;
return x * i;
});
Wenn ich auf diese beobachtbaren abonnieren zweimal ich diese beiden Sequenzen erhalten:
(1)
0
-4
16
-48
128
-320
768
-1792
4096
-9216
(2)
0
-4096
16384
-49152
131072
-327680
786432
-1835008
4194304
-9437184
Die Reihenfolge ändert sich weil ich den Staat benutzt habe (d.h. var i = -1;
).
Hätte ich den Code mit Observable.Create
geschrieben ich diesen Zustand vermeiden könnte:
var query =
Observable
.Create<int>(o =>
{
var i = -1;
return
Observable
.Range(0, 10).Select(x =>
{
i = -i * 2;
return x * i;
})
.Subscribe(o);
});
Es ist immer noch die gleiche Abfrage, aber der Staat ist gekapselt, also wenn ich jetzt zweimal abonniere ich bekommen:
(1)
0
-4
16
-48
128
-320
768
-1792
4096
-9216
(2)
0
-4
16
-48
128
-320
768
-1792
4096
-9216
Es gibt Zeiten, wenn komplexe Abfragen geschrieben werden, die Sie vielleicht denken, dass die Verwendung eines Betreffs es viel einfacher machen würde und im Allgemeinen Fehler auftreten. Sie sollten immer versuchen, einen reinen Operatoransatz zu finden, bevor Sie in diesem Fall Subjekte verwenden. Wenn Sie dann nicht die Verwendung eines Betreffs in Observable.Create
kapseln können.
Es ist Zeiten wie Ihre, dass die Verwendung eines Betreffs in Ordnung ist, weil Sie diesen externen Zustand benötigen.
Ich gab ein minimales Beispiel für SO. Der echte Code ist komplexer als das. – sdgfsdh
Das ist gut zu hören. Aber wenn dies ein vollständiges minimales nachprüfbares Beispiel ist, dann ist der Subjekt (und somit Rx) überflüssig. Ich glaube nicht, dass Sie genügend Informationen liefern, um eine vernünftige Antwort zu geben. –
Ein Beispiel dafür, wo mein 'IObservable' nützlich ist, ist die Verarbeitung der Eingabe. Wenn ich auch einen 'IObservable ' habe, kann ich es mit meinem 'GameTime'-Stream anzeigen. –
sdgfsdh