Skip to content

Instantly share code, notes, and snippets.

@hodzanassredin
Created July 8, 2014 07:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hodzanassredin/e6b5e70a46201251629e to your computer and use it in GitHub Desktop.
Save hodzanassredin/e6b5e70a46201251629e to your computer and use it in GitHub Desktop.
WokflowEngine in c#
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Newtonsoft.Json;
using System.Reflection;
using System.IO;
using System.ComponentModel;
using System.Globalization;
namespace Tutorial1v2
{
class MainClass
{
public class SumWorkflow:Workflow<int>
{
public SumWorkflow ()
{
}
public SumWorkflow (ExecutionContext context) : base (context)
{
}
public override WorkflowStep<int> GetResultInt ()
{
return from a in Ask<int> ("enter a")
from b in Ask<int> ("enter b")
let res = a + b
from x in Show ("Result= " + res)
select res;
}
}
public class WorkflowComposition:Workflow<int>
{
public override WorkflowStep<int> GetResultInt ()
{
return from a in new SumWorkflow (Context).GetResult ()
from b in new SumWorkflow (Context).GetResult ()
let res = a + b
from v in Show ("Result of two = " + (a + b))
select a + b;
}
}
public static void Main (string[] args)
{
var fileName = "workflow.json";
var wrkfl = Storage.Load<WorkflowComposition> (fileName);
Console.WriteLine ("Current workflow state");
foreach (var item in wrkfl.Context.Memory) {
Console.WriteLine (item);
}
var res = wrkfl.GetResult ();
if (res.IsExecuted ()) {
Console.WriteLine ("Finished");
File.Delete (fileName);
} else {
if (res.Action is Show) {
Console.WriteLine ((res.Action as Show).What);
wrkfl.AddResult (Unit.Value);
} else if (res.Action is Ask<int>) {
Console.WriteLine ((res.Action as Ask<int>).What);
var resp = Console.ReadLine ();
var val = int.Parse (resp);
wrkfl.AddResult (val);
}
Storage.Save (wrkfl, fileName);
}
}
}
public static class WorkflowMonad
{
public static WorkflowStep<T> Return<T> (this T value)
{
return new WorkflowStep<T> (value);
}
public static WorkflowStep<U> Bind<T, U> (this WorkflowStep<T> m, Func<T, WorkflowStep<U>> k)
{
if (m.IsExecuted ()) {
return k (m.GetValue ());
}
return new WorkflowStep<U> (m.Action, m.Context, m.Index);
}
public static WorkflowStep<V> SelectMany<T, U, V> (
this WorkflowStep<T> id,
Func<T, WorkflowStep<U>> k,
Func<T, U, V> s)
{
return id.Bind (x => k (x).Bind (y => s (x, y).Return ()));
}
public static WorkflowStep<B> Select<A, B> (this WorkflowStep<A> a, Func<A, B> select)
{
return a.Bind (aval => WorkflowMonad.Return (select (aval)));
}
}
public class ExecutionContext
{
public ExecutionContext ()
{
Memory = new List<string> ();
}
public List<string> Memory {
get;
set;
}
public int Index {
get;
private set;
}
public void ClearIndex ()
{
Index = 0;
}
public void Inc ()
{
Index = Index + 1;
}
}
public class Unit
{
Unit ()
{
}
public static Unit Value = new Unit ();
}
public class Action
{
}
public class Show : Action
{
public string What {
get;
set;
}
}
public class Ask<T> : Action
{
public string What {
get;
set;
}
}
public abstract class Workflow<TB>
{
public Workflow ()
{
Context = new ExecutionContext ();
}
public Workflow (ExecutionContext ctx)
{
Context = ctx;
IsSubWorkflow = true;
}
public bool IsSubWorkflow {
get;
set;
}
public ExecutionContext Context {
get;
set;
}
protected WorkflowStep<T> Do<T> (Action act)
{
var step = new WorkflowStep<T> (act, Context, Context.Index);
Context.Inc ();
return step;
}
protected WorkflowStep<T> Ask<T> (String what)
{
return Do<T> (new Ask<T> (){ What = what });
}
protected WorkflowStep<Unit> Show (String what)
{
return Do<Unit> (new Show (){ What = what });
}
public abstract WorkflowStep<TB> GetResultInt ();
public WorkflowStep<TB> GetResult ()
{
if (!IsSubWorkflow)
Context.ClearIndex ();
return GetResultInt ();
}
public void AddResult (object val)
{
Context.Memory.Add (val.ValueToString ());
}
}
public class WorkflowStep<T>
{
public WorkflowStep (Action act, ExecutionContext context, int index)
{
Action = act;
Context = context;
Index = index;
}
public WorkflowStep (T value)
{
Context.Memory.Add (value.ValueToString ());
}
public ExecutionContext Context = new ExecutionContext ();
public Action Action {
get;
private set;
}
public bool IsExecuted ()
{
return (this.Index) < Context.Memory.Count;
}
public T GetValue ()
{
return Context.Memory [this.Index].ParseValue<T> ();
}
public int Index {
get;
set;
}
public WorkflowStep<TB> Bind<TB> (Func<T,WorkflowStep<TB>> f)
{
if (this.IsExecuted ()) {
return f (this.GetValue ());
}
return new WorkflowStep<TB> (this.Action, this.Context, this.Index);
}
public static WorkflowStep<TB> Return<TB> (TB x)
{
return new WorkflowStep<TB> (x);
}
}
public static class Helpers
{
public static T ParseValue<T> (this string json)
{
return JsonConvert.DeserializeObject<T> (json);
}
public static string ValueToString<T> (this T value)
{
return JsonConvert.SerializeObject (value);
}
}
public class Storage
{
static JsonSerializerSettings settings;
static Storage ()
{
settings = new JsonSerializerSettings ();
}
public static void Save<T> (T wrkfl, String name)
{
var json = JsonConvert.SerializeObject (wrkfl, settings);
File.WriteAllText (name, json);
}
public static T Load<T> (string name)
where T:new()
{
if (File.Exists (name)) {
var json = File.ReadAllText (name);
return JsonConvert.DeserializeObject<T> (json, settings);
}
return new T ();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment