Reputation: 10548
As per an earlier question, I was told by a user that I should not expose a .NET Event-style API unless absolutely forced to:
If you're not positively forced to do so, do not make an API using C# style events.
In this case, how should I implement an "event" whereby a model will notify any observers that it has changed in some way? The event is only expected to be called once. Let's say for example that my model is a Minecraft Block, and I invoke the method Destroy()
on this model. The Destroy()
method should broadcast to it's observers that that model intends to be destroyed. Example observers would be a controller that would then send a BlockDestroyed
notification to the view (I appreciate the controller could be an unnecessary level of indirection however it is a lot easier to do model -> controller -> view rather than model (observable) -> view (observer)).
Here is my code that I would intend to alter to an Rx style - remember, Destroyed
would only be invoked once per block - and there could be other events, such as Damaged
, Activated
, and TextureChanged
.
public class Block
{
public Block()
{
}
/// <summary>
/// Destroy the block.
/// </summary>
public void Destroy()
{
var msg = new BlockDestroyedMessage();
if (Destroyed != null)
Destroyed(this, msg);
}
public event EventHandler<BlockDestroyedMessage> Destroyed;
}
Also note that I am seeing documentation over the web that basically you
ISubject<T>
because it encourages violating the SRP (which I agree with)IObservable<T>
(because there are so many factory methods for creating observables)Upvotes: 1
Views: 123
Reputation: 117175
I would do this:
public class Block
{
public void Destroy()
{
if (_destroyed != null)
{
var msg = new BlockDestroyedMessage();
_destroyed.OnNext(msg);
_destroyed.OnCompleted();
_destroyed = null;
}
}
private Subject<BlockDestroyedMessage> _destroyed
= new Subject<BlockDestroyedMessage>();
public readonly IObservable<BlockDestroyedMessage> Destroyed
= _destroyed.AsObservable();
}
Upvotes: 1