Skip to content

Instantly share code, notes, and snippets.

@ryupold
Created April 2, 2019 21:29
Show Gist options
  • Save ryupold/e4f4a2279d608dff76584b14615f7b3e to your computer and use it in GitHub Desktop.
Save ryupold/e4f4a2279d608dff76584b14615f7b3e to your computer and use it in GitHub Desktop.
typesafe generic command execution
using System;
using System.Threading.Tasks;
namespace Cli
{
public class Program
{
static void Main(string[] args)
{
var cmdr = new Commander<Unit, string>(() => new ReturnStuffCommnad<string>("12345"))
.AddCommand(() => new StringToIntCommand())
.AddCommand(() => new AddOneCommand())
.AddCommand(() => new AddOneCommand())
.AddCommand(() => new ToStringCommand<int>());
Console.WriteLine(cmdr.DoIt(Unit.Default).Result); //"12347"
}
}
public interface ICommand<TInput, TResult>
{
Task<TResult> DoStuff(TInput input);
}
public class Commander<TInput, TResult>
{
private Commander() { }
public Commander(Func<ICommand<TInput, TResult>> firstCommandFactory)
{
_todo = async (TInput input) => await firstCommandFactory().DoStuff(input);
}
private Func<TInput, Task<TResult>> _todo;
public Commander<TInput, TNewResult> AddCommand<TNewResult>(Func<ICommand<TResult, TNewResult>> commandFactory)
{
return new Commander<TInput, TNewResult>()
{
_todo = async (TInput input) =>
{
var result = await this._todo(input);
return await commandFactory().DoStuff(result);
}
};
}
public async Task<TResult> DoIt(TInput input)
{
return await _todo(input);
}
}
public class ReturnStuffCommnad<T> : ICommand<Unit, T>
{
private readonly T _stuff;
public ReturnStuffCommnad(T stuff)
{
_stuff = stuff;
}
public Task<T> DoStuff(Unit input)
{
return Task.FromResult(_stuff);
}
}
public class ToStringCommand<T> : ICommand<T, string>
{
public Task<string> DoStuff(T input)
{
return Task.FromResult("" + input);
}
}
public class AddOneCommand : ICommand<int, int>
{
public Task<int> DoStuff(int input)
{
return Task.FromResult(input + 1);
}
}
public class StringToIntCommand : ICommand<string, int>
{
public Task<int> DoStuff(string input)
{
return Task.FromResult(int.Parse(input));
}
}
public class Unit
{
private Unit() { }
private static readonly Unit _default = new Unit();
public static Unit Default => _default;
public override bool Equals(object obj) { return obj is Unit; }
public override int GetHashCode() { return 1; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment