Skip to content

Instantly share code, notes, and snippets.

@LeeCampbell
Created May 11, 2016 08:35
Show Gist options
  • Save LeeCampbell/06dcd6ce37a33b67ef9c98b7a8cea3d9 to your computer and use it in GitHub Desktop.
Save LeeCampbell/06dcd6ce37a33b67ef9c98b7a8cea3d9 to your computer and use it in GitHub Desktop.
An example of a LeftFold helper for Cedar EventStore lib.
using System;
using System.Collections.Generic;
using System.Globalization;
using Cedar.EventStore.Streams;
namespace DunkyMoleFanClub
{
public static class LeftFold
{
public static readonly string DefaultKey = string.Empty;
public static LeftFoldPlan<T> Over<T>()
{
return new LeftFoldPlan<T>();
}
}
public class LeftFoldPlan<TAccumulator>
{
private readonly IDictionary<string, Func<TAccumulator, StreamEvent, TAccumulator>> _folds =
new Dictionary<string, Func<TAccumulator, StreamEvent, TAccumulator>>();
/// <summary>
/// Provide a strongly-typed left-fold function.
/// </summary>
/// <param name="eventType">The event type to apply the left fold on</param>
/// <param name="fold">
/// The function used to apply the left fold.
/// The function is provided with the accumulator, the strongly-typed event and the current position of the event.
/// The function returns the updated value of the accumulator.
/// </param>
/// <returns>
/// Returns the updated instance of the <see cref="LeftFoldPlan{TAccumulator}"/>.
/// Allows for method chaining.
/// </returns>
public LeftFoldPlan<TAccumulator> With(string eventType, Func<TAccumulator, StreamEvent, TAccumulator> fold)
{
if (_folds.ContainsKey(eventType))
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Fold over '{0}' already registered", eventType));
_folds[eventType] = fold;
return this;
}
public LeftFoldPlan<TAccumulator> WithDefault(Func<TAccumulator, StreamEvent, TAccumulator> fold)
{
if (_folds.ContainsKey(LeftFold.DefaultKey))
throw new ArgumentException("Default Fold is already registered");
_folds[LeftFold.DefaultKey] = fold;
return this;
}
public LeftFolder<TAccumulator> Build()
{
return new LeftFolder<TAccumulator>(_folds);
}
}
public class LeftFolder<T>
{
private readonly IDictionary<string, Func<T, StreamEvent, T>> _folds;
public LeftFolder(IDictionary<string, Func<T, StreamEvent, T>> folds)
{
_folds = folds;
}
public T ApplyFold(T accumulator, StreamEvent currentEvent)
{
var key = currentEvent.Type;
if (_folds.ContainsKey(key))
return _folds[key](accumulator, currentEvent);
if (_folds.ContainsKey(LeftFold.DefaultKey))
return _folds[LeftFold.DefaultKey](accumulator, currentEvent);
return accumulator;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment