Skip to content

Instantly share code, notes, and snippets.

@florimm
Created September 10, 2018 22:45
Show Gist options
  • Save florimm/fd88626e5bae1749c84827d5d6b56c57 to your computer and use it in GitHub Desktop.
Save florimm/fd88626e5bae1749c84827d5d6b56c57 to your computer and use it in GitHub Desktop.
void Main()
{
var pipeline = new LoggerHandler(new TryHandler());
var wf = FunctionFlow
.Init()
.Run(r => GetEmail("florim"))
.Run(r => SendEmail(r))
.ProcessWithPipelines(pipeline) // or //.Process()
.GetAwaiter().GetResult().Dump();
}
public static async Task<Result<string>> GetEmail(string name)
{
await Task.Delay(2000);
"getting email".Dump();
return Result.Ok($"{name}@gmail.com");
}
public static Task<Result<bool>> SendEmail(string email)
{
"sending email".Dump();
return Task.FromResult(Result.Ok<bool>(true));
}
public interface IHandler
{
Task<Result<TR>> Handle<TR>(Func<Task<Result<TR>>> func);
}
public class LoggerHandler : IHandler
{
public IHandler next;
public LoggerHandler(IHandler handler = null)
{
this.next = handler;
}
public async Task<Result<TR>> Handle<TR>(Func<Task<Result<TR>>> func)
{
"-----------------------------------------".Dump();
Result<TR> result;
if (this.next != null)
{
result = await this.next.Handle(func);
}
else
{
result = await func();
}
"-----------------------------------------".Dump();
return result;
}
}
public class TryHandler : IHandler
{
public IHandler next;
public TryHandler(IHandler handler = null)
{
this.next = handler;
}
public async Task<Result<TR>> Handle<TR>(Func<Task<Result<TR>>> func)
{
"Try 1 started".Dump();
Result<TR> result;
try
{
if (this.next != null)
{
result = await this.next.Handle(func);
}
else
{
result = await func();
}
"Try 1 ended".Dump();
return result;
}
catch (Exception ex)
{
$"Error {ex.Message}".Dump();
return Result.Fail<TR>(ex.Message);
}
}
}
public class EmptyHandler : IHandler
{
public async Task<Result<TR>> Handle<TR>(Func<Task<Result<TR>>> func)
{
return await func();
}
}
public class FunctionFlow
{
private FunctionFlow() {}
public static FunctionFlowResult<FunctionFlow> Init()
{
var fw = new FunctionFlow();
return (handler) =>
{
return Task.FromResult(Result.Ok(fw));
};
}
}
public static class FunctionFlowExtensions
{
public static Task<Result<T>> ProcessWithPipelines<T>(this FunctionFlowResult<T> src, IHandler handler)
{
return src(handler);
}
public static Task<Result<T>> Process<T>(this FunctionFlowResult<T> src)
{
return src(new EmptyHandler());
}
public static FunctionFlowResult<TR> Run<T, TR>(this FunctionFlowResult<T> src, Func<T, Task<Result<TR>>> func)
{
return async (handler) =>
{
var data = await src(handler);
if (data.IsSuccess)
{
return await handler.Handle(() => func(data.Value));
}
return Result.Fail<TR>(data.Error);
};
}
}
public interface IContext
{
}
public delegate Task<Result<T>> FunctionFlowResult<T>(IHandler handler);
public class Result
{
public bool IsSuccess { get; }
public string Error { get; }
public bool IsFailure => !IsSuccess;
protected Result(bool isSuccess, string error)
{
if (isSuccess && error != string.Empty)
throw new InvalidOperationException();
if (!isSuccess && error == string.Empty)
throw new InvalidOperationException();
IsSuccess = isSuccess;
Error = error;
}
public static Result Fail(string message)
{
return new Result(false, message);
}
public static Result<T> Fail<T>(string message)
{
return new Result<T>(default(T), false, message);
}
public static Result Ok()
{
return new Result(true, string.Empty);
}
public static Result<T> Ok<T>(T value)
{
return new Result<T>(value, true, string.Empty);
}
public static Result Combine(params Result[] results)
{
foreach (Result result in results)
{
if (result.IsFailure)
return result;
}
return Ok();
}
}
public class Result<T> : Result
{
private readonly T _value;
public T Value
{
get
{
if (!IsSuccess)
throw new InvalidOperationException();
return _value;
}
}
protected internal Result(T value, bool isSuccess, string error)
: base(isSuccess, error)
{
_value = value;
}
}
public sealed class Unit : IComparable
{
public static readonly Unit Value = new Unit();
public override int GetHashCode()
{
return 0;
}
public override bool Equals(object obj)
{
return obj == null || obj is Unit;
}
int IComparable.CompareTo(object obj)
{
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment