Ключевая проблема, с которой вы сталкиваетесь здесь, заключается в том, что вам нужен источник для вашего наблюдаемого. В общем, вы можете создавать наблюдаемые объекты из различных источников, таких как события, делегаты, задачи, многие наблюдаемые расширения (например, .Interval
или .Generate
) и темы.
В вашем случае у вас должен быть источник, в котором вы можете иметь код, внешний по отношению к вашему наблюдаемому, нажимать значения. В этом случае с субъектом все в порядке, но вы также можете просто использовать делегата.
Если вы используете тему, то ваш код в порядке. Единственным недостатком является то, что вы можете вызвать updateSubject.OnCompleted
и закончить наблюдаемое.
Если вы хотите использовать делегата, ваш код может выглядеть так:
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);
}
Таким образом, единственное, что вы можете сделать с updateGameTime
, это передать новый GameTime
- вы не можете "случайно" закончить последовательность.
Теперь вся проблема с использованием субъектов по сравнению с Observable.Create
связана с состоянием. В вашем коде вам нужно состояние, поэтому тема в порядке. Однако в целом, по возможности, желательно инкапсулировать состояние - и это то, что Observable.Create
делает для вас.
Возьмите этот пример:
var i = -1;
var query =
Observable
.Range(0, 10).Select(x =>
{
i = -i * 2;
return x * i;
});
Если я подпишусь на эту наблюдаемую дважды, я получу эти две последовательности:
(1)
0
-4
16
-48
128
-320
768
-1792
4096
-9216
(2)
0
-4096
16384
-49152
131072
-327680
786432
-1835008
4194304
-9437184
Последовательность меняется, потому что я использовал состояние (т.е. var i = -1;
).
Если бы я написал код с Observable.Create
, я мог бы избежать этого состояния:
var query =
Observable
.Create<int>(o =>
{
var i = -1;
return
Observable
.Range(0, 10).Select(x =>
{
i = -i * 2;
return x * i;
})
.Subscribe(o);
});
Это все тот же запрос, но состояние инкапсулировано, поэтому, если я подпишусь дважды, я получу:
(1)
0
-4
16
-48
128
-320
768
-1792
4096
-9216
(2)
0
-4
16
-48
128
-320
768
-1792
4096
-9216
Бывают случаи, когда при написании сложных запросов вы можете подумать, что использование темы значительно облегчит задачу, и в целом именно здесь случаются ошибки. Вы всегда должны пытаться найти чисто операторный подход, прежде чем использовать субъекты в этом случае. Если вы не можете инкапсулировать использование субъекта в Observable.Create
.
В такие времена, как ваше, использование темы — это нормально, потому что вам нужно это внешнее состояние.
person
Enigmativity
schedule
04.07.2016