Add Versioned, Recorded and FSM
This commit is contained in:
parent
ef746d69ba
commit
c95a809bfd
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0; net48</TargetFrameworks>
|
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||||
<RootNamespace>lib</RootNamespace>
|
<RootNamespace>lib</RootNamespace>
|
||||||
<AssemblyVersion>0.0.1.0</AssemblyVersion>
|
<AssemblyVersion>0.0.1.0</AssemblyVersion>
|
||||||
<FileVersion>0.0.1.0</FileVersion>
|
<FileVersion>0.0.1.0</FileVersion>
|
||||||
@ -25,7 +25,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Properties\" />
|
<Folder Include="Properties\" />
|
||||||
<Folder Include="reflect\" />
|
<Folder Include="reflect\" />
|
||||||
|
<Folder Include="fsm\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="fsm\" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
61
fsm/FSM.cs
Normal file
61
fsm/FSM.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace fsm;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public record class Context : imm.Recorded<Context>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public record class State<T, CTX> : imm.Recorded<State<T, CTX>>
|
||||||
|
where T: State<T, CTX>
|
||||||
|
where CTX: Context
|
||||||
|
{
|
||||||
|
virtual public (CTX, T) onEnter(CTX ctx, State<T, CTX> oldState)
|
||||||
|
{
|
||||||
|
return (ctx, (T)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual public (CTX, T) onExit(CTX ctx, State<T, CTX> newState)
|
||||||
|
{
|
||||||
|
return (ctx, (T)this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record class FSM<T, CTX, ST> : imm.Recorded<FSM<T, CTX, ST>>
|
||||||
|
where T: FSM<T, CTX, ST>
|
||||||
|
where CTX: Context
|
||||||
|
where ST: State<ST, CTX>
|
||||||
|
{
|
||||||
|
public CTX Context { get; private set; }
|
||||||
|
public ST State { get; private set; }
|
||||||
|
|
||||||
|
public FSM(CTX context, ST state)
|
||||||
|
{
|
||||||
|
Context = context;
|
||||||
|
State = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FSM<T, CTX, ST> Transition(ST newState)
|
||||||
|
{
|
||||||
|
var (newOldCTX, oldState) = State.onExit(Context, newState);
|
||||||
|
|
||||||
|
var (newCTX, storeState) = newState.onEnter(newOldCTX, oldState);
|
||||||
|
|
||||||
|
return this with
|
||||||
|
{
|
||||||
|
Context = newCTX,
|
||||||
|
State = storeState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
87
imm/Imm.cs
87
imm/Imm.cs
@ -2,14 +2,93 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
// A spot for immutable helpers
|
// A spot for immutable helpers
|
||||||
|
|
||||||
public static class imm
|
namespace imm
|
||||||
{
|
{
|
||||||
|
public record class Versioned<T>
|
||||||
|
where T: Versioned<T>
|
||||||
|
{
|
||||||
|
public uint Version { get; protected set; } = 0;
|
||||||
|
public string Reason { get; protected set; } = "";
|
||||||
|
|
||||||
|
public T Process(Func<T, T> fn, string reason = "")
|
||||||
|
{
|
||||||
|
var newT = fn((T)this);
|
||||||
|
|
||||||
|
return newT with
|
||||||
|
{
|
||||||
|
Version = newT.Version + 1,
|
||||||
|
Reason = reason,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record class Recorded<T> : Versioned<T>
|
||||||
|
where T : Recorded<T>
|
||||||
|
{
|
||||||
|
public T? Old { get; private set; }
|
||||||
|
public string Expression { get; private set; } = "";
|
||||||
|
public string MemberName { get; private set; } = "";
|
||||||
|
public string FilePath { get; private set; } = "";
|
||||||
|
public int LineNumber { get; private set; } = -1;
|
||||||
|
|
||||||
|
public T Record(string reason = "",
|
||||||
|
[CallerMemberName] string memberName = "",
|
||||||
|
[CallerFilePath] string filePath = "",
|
||||||
|
[CallerLineNumber] int lineNumber = 0)
|
||||||
|
{
|
||||||
|
var orig = (T)this;
|
||||||
|
|
||||||
|
var newT = base.Process((old) => old with
|
||||||
|
{
|
||||||
|
Old = orig,
|
||||||
|
MemberName = memberName,
|
||||||
|
FilePath = filePath,
|
||||||
|
LineNumber = lineNumber,
|
||||||
|
}, reason);
|
||||||
|
|
||||||
|
return newT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public T Process(Func<T, T> fn, string reason = "",
|
||||||
|
[CallerMemberName] string memberName = "",
|
||||||
|
[CallerFilePath] string filePath = "",
|
||||||
|
[CallerLineNumber] int lineNumber = 0,
|
||||||
|
[CallerArgumentExpression("fn")]
|
||||||
|
string expression = default)
|
||||||
|
{
|
||||||
|
var orig = (T)this;
|
||||||
|
|
||||||
|
return (T)this with
|
||||||
|
{
|
||||||
|
//Do the Versioned code here
|
||||||
|
Version = orig.Version + 1,
|
||||||
|
|
||||||
|
//Recorded
|
||||||
|
Old = orig,
|
||||||
|
Expression = expression,
|
||||||
|
MemberName = memberName,
|
||||||
|
FilePath = filePath,
|
||||||
|
LineNumber = lineNumber,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Util
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user