Skip to content

Instantly share code, notes, and snippets.

@jen20
Created July 11, 2018 15:51
Show Gist options
  • Save jen20/08c7ba865ef5dd95ff1a8c9d351f60ec to your computer and use it in GitHub Desktop.
Save jen20/08c7ba865ef5dd95ff1a8c9d351f60ec to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
namespace Messaging101 {
/* Create inventory bucket
* Check into inventory (quantity)
* Check out of inventory (quantity)
* throw Exception
*/
public static class Program {
public interface Command {}
public class CheckItemOut : Command {
public readonly uint Quantity;
public CheckItemOut(uint quantity) {
Quantity = quantity;
}
}
public interface IHandle<in T> where T : Command {
void Handle(T message);
}
public class NarrowingHandler<T, V> : IHandle<T> where T : Command where V : T {
private IHandle<V> _next;
public NarrowingHandler(IHandle<V> next) {
_next = next;
}
public void Handle(T message) {
_next.Handle((V)message);
}
}
public class LoggingHandler<T> : IHandle<T> where T : Command {
private IHandle<T> _next;
public LoggingHandler(IHandle<T> next) {
_next = next;
}
public void Handle(T message) {
Console.WriteLine($"About to do command: {message.GetType()}");
_next.Handle(message);
Console.WriteLine($"Finished doing command: {message.GetType()}");
}
}
public class CheckItemOutHandler : IHandle<CheckItemOut> {
private static List<Event> _history = new List<Event> {
new ItemCheckedIn(100),
new ItemCheckedOut(50)
};
public void Handle(CheckItemOut message) {
// Load object from history
var obj = new InventoryBucket(_history);
// Call CheckItemOut
obj.CheckItemOut(message.Quantity);
var producedEvents = obj.GetProducedEvents();
if (producedEvents.Count > 0) {
_history.AddRange(producedEvents);
foreach (var e in producedEvents) {
Console.WriteLine("Produced: " + e);
}
}
}
}
public static void Main() {
var checkItemOutPipeline =
new LoggingHandler<CheckItemOut>(
new CheckItemOutHandler());
checkItemOutPipeline.Handle(new CheckItemOut(10));
//
//
// var bucket = new InventoryBucket();
// bucket.CheckItemIn(100);
// bucket.CheckItemOut(10);
// bucket.CheckItemOut(10);
// bucket.CheckItemIn(100);
//
// var history = bucket.GetProducedEvents();
// // Save in the database
//
//
// Debugger.Break();
}
}
public class InventoryBucket {
private uint _quantityOnHand;
public override string ToString() {
return $"Inventory Item: Count: {_quantityOnHand}";
}
private List<Event> _producedEvents = new List<Event>();
public List<Event> GetProducedEvents() {
var toReturn = _producedEvents;
_producedEvents = new List<Event>();
return toReturn;
}
private void RaiseEvent(Event @event) {
_producedEvents.Add(@event);
Apply(@event);
}
public InventoryBucket(List<Event> history) {
foreach (var @event in history) {
Apply(@event);
}
}
public InventoryBucket() {}
private void Apply(Event @event) {
switch (@event)
{
case ItemCheckedIn e:
_quantityOnHand += e.Quantity;
break;
case ItemCheckedOut e:
_quantityOnHand -= e.Quantity;
break;
default:
throw new ArgumentException("wtf");
}
}
public void CheckItemIn(uint quantity) {
if (quantity == 0) {
throw new ArgumentException("quantity");
}
RaiseEvent(new ItemCheckedIn(quantity));
}
public void CheckItemOut(uint quantity) {
if (quantity == 0) {
throw new ArgumentException("quantity");
}
if (_quantityOnHand < quantity) {
throw new ArgumentException("quantity");
}
RaiseEvent(new ItemCheckedOut(quantity));
}
}
public interface Event {
}
public class ItemCheckedOut : Event {
public readonly uint Quantity;
public ItemCheckedOut(uint quantity) {
Quantity = quantity;
}
}
public class ItemCheckedIn : Event {
public readonly uint Quantity;
public ItemCheckedIn(uint quantity) {
Quantity = quantity;
}
}
public class InventoryBucketCreated : Event {
public readonly string ItemName;
public readonly uint OpeningCount;
public InventoryBucketCreated(string itemName, uint openingCount) {
ItemName = itemName;
OpeningCount = openingCount;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment