Skip to content

Instantly share code, notes, and snippets.

@yreynhout
Last active August 29, 2015 14:01
Show Gist options
  • Save yreynhout/247e164966439385dbf3 to your computer and use it in GitHub Desktop.
Save yreynhout/247e164966439385dbf3 to your computer and use it in GitHub Desktop.
Parking it here
using System;
using System.Linq;
namespace FiveMinuteProject
{
public class ProjectionBuilder<TState>
{
private readonly ProjectionHandler<TState>[] _handlers;
public ProjectionBuilder()
{
_handlers = new ProjectionHandler<TState>[0];
}
ProjectionBuilder(ProjectionHandler<TState>[] handlers)
{
_handlers = handlers;
}
public ProjectionBuilder<TState> When<TEvent>(Func<TState, TEvent, TState> handler)
{
return new ProjectionBuilder<TState>(
_handlers.
Concat(new[]
{
new ProjectionHandler<TState>(
typeof (TEvent),
(state, @event) => handler(state, (TEvent) @event))
}).
ToArray());
}
public Projection<TState> Build()
{
return new Projection<TState>(_handlers);
}
}
public class Projection<TState>
{
private readonly ProjectionHandler<TState>[] _handlers;
public Projection(ProjectionHandler<TState>[] handlers)
{
if (handlers == null) throw new ArgumentNullException("handlers");
_handlers = handlers;
}
public TState Project(TState state, object @event)
{
return _handlers.Aggregate(state, (current, handler) => handler.Handle(current, @event));
}
}
public class ProjectionHandler<TState>
{
private readonly Type _event;
private readonly Func<TState, object, TState> _handler;
public ProjectionHandler(Type @event, Func<TState, object, TState> handler)
{
if (@event == null) throw new ArgumentNullException("event");
if (handler == null) throw new ArgumentNullException("handler");
_event = @event;
_handler = handler;
}
public Type Event { get { return _event; } }
public Func<TState, object, TState> Handler { get { return _handler; } }
public TState Handle(TState state, object @event)
{
if (@event == null) throw new ArgumentNullException("event");
return Event.IsInstanceOfType(@event) ? Handler(state, @event) : state;
}
}
//public static class Projections
//{
// public static readonly Projection<ImmutableList<Tuple<Guid, Guid, string>>> OrderProductHistory =
// new ProjectionBuilder<ImmutableList<Tuple<Guid, Guid, string>>>().
// When<SomeEvent1>(
// (state, msg) =>
// state.Add(new Tuple<Guid, Guid, string>(msg.OrderId, msg.ProductId, msg.GetType().Name))).
// When<SomeEvent2>(
// (state, msg) =>
// state.Add(new Tuple<Guid, Guid, string>(msg.OrderId, msg.ProductId, msg.GetType().Name))).
// When<SomeEvent3>(
// (state, msg) =>
// state.Add(new Tuple<Guid, Guid, string>(msg.OrderId, msg.ProductId, msg.GetType().Name))).
// When<SomeEvent4>(
// (state, msg) =>
// state.Add(new Tuple<Guid, Guid, string>(msg.OrderId, msg.ProductId, msg.GetType().Name))).
// Build();
//}
// usage:
// var state = ImmutableList.Create<Tuple<Guid, Guid, string>>();
// foreach(var @event in stream) { state = Projections.OrderProductHistory.Project(state, @event); }
// OutputStateInFancyWay(state);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment