-
-
Save yreynhout/4716699 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Reactive; | |
using System.Reactive.Subjects; | |
namespace NaiveEventSourcing { | |
class Program { | |
static void Main(string[] args) { | |
var travelerRepository = new AlwaysNewTravelerRepository(); | |
var travelerService = new TravelerService(travelerRepository); | |
var travelerId = Guid.NewGuid(); | |
travelerService.Handle(new TakeItemCommand(travelerId, "Tootbrush")); | |
travelerService.Handle(new TakeItemCommand(travelerId, "Map")); | |
Console.ReadLine(); | |
travelerService.Handle(new TakeItemCommand(travelerId, "CellphoneCharger")); | |
Console.ReadLine(); | |
} | |
} | |
public interface ITravelerRepository { | |
Traveler Get(Guid id); | |
} | |
public class AlwaysNewTravelerRepository : ITravelerRepository { | |
public Traveler Get(Guid id) { | |
return new Traveler(new [] { new BecameTraveller() }); | |
} | |
} | |
// Service handles commands, and translates them to events which will get applied to the AR | |
public class TravelerService : IHandle<TakeItemCommand> { | |
readonly ITravelerRepository _repository; | |
public TravelerService(ITravelerRepository repository) { | |
if (repository == null) throw new ArgumentNullException("repository"); | |
_repository = repository; | |
} | |
public void Handle(TakeItemCommand command) { | |
var traveller = _repository.Get(command.Id); | |
traveller.Subscribe(@event => Console.WriteLine(@event.GetType().Name)); | |
traveller.TakeItem(command.ItemName); | |
} | |
} | |
public interface IHandle<T> where T : ICommand { | |
void Handle(T command); | |
} | |
public interface ICommand { } | |
public class TakeItemCommand : ICommand { | |
public TakeItemCommand(Guid id, string itemName) { | |
Id = id; | |
ItemName = itemName; | |
} | |
public string ItemName { get; private set; } | |
public Guid Id { get; private set; } | |
} | |
public class Traveler : ObservableBase<Object> { | |
readonly Subject<object> _source; | |
private List<TravelerItem> _items; | |
public Traveler(IEnumerable<Object> stream) { | |
_source = new Subject<Object>(); | |
foreach (var @event in stream) { | |
Play(@event); | |
} | |
} | |
public void TakeItem(string itemName) { | |
//Guards go here ... e.g. Enforce.That(itemName.Length > 0 && itemName.Length < MetaData.ItemNameMaxLength); | |
Apply(new TookItemEvent(itemName)); | |
} | |
void Apply(object @event) { | |
Play(@event); | |
Record(@event); | |
} | |
void Play(object @event) { | |
((dynamic)this).When((dynamic)@event); | |
} | |
void Record(object @event) { | |
_source.OnNext(@event); | |
} | |
void When(BecameTraveller @event) { | |
_items = new List<TravelerItem>(); | |
} | |
void When(TookItemEvent @event) { | |
_items.Add(new TravelerItem(@event.Name)); | |
} | |
protected override IDisposable SubscribeCore(IObserver<object> observer) { | |
return _source.Subscribe(observer); | |
} | |
} | |
public class TravelerItem { | |
public TravelerItem(string name) { | |
Name = name; | |
} | |
public string Name { get; private set; } | |
} | |
public interface IEvent { } | |
public class BecameTraveller : IEvent { } | |
public class TookItemEvent : IEvent { | |
public TookItemEvent(string name) { | |
Name = name; | |
} | |
public string Name { get; private set; } | |
public override string ToString() { | |
return "Took " + Name; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment