Created
April 2, 2019 21:29
-
-
Save ryupold/e4f4a2279d608dff76584b14615f7b3e to your computer and use it in GitHub Desktop.
typesafe generic command execution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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