Created
September 10, 2018 22:45
-
-
Save florimm/fd88626e5bae1749c84827d5d6b56c57 to your computer and use it in GitHub Desktop.
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
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