Skip to content

Instantly share code, notes, and snippets.

@yreynhout
Forked from JefClaes/gist:4716622
Last active December 12, 2015 04:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yreynhout/4716699 to your computer and use it in GitHub Desktop.
Save yreynhout/4716699 to your computer and use it in GitHub Desktop.
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