Created
July 8, 2014 07:13
-
-
Save hodzanassredin/e6b5e70a46201251629e to your computer and use it in GitHub Desktop.
WokflowEngine in c#
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.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