Various immutable changes

This commit is contained in:
Marc Hernandez 2024-01-21 22:16:02 -08:00
parent dbdd6ea748
commit 71a7a115e2
3 changed files with 195 additions and 111 deletions

View File

@ -9,16 +9,65 @@ using System.Threading.Tasks;
// A spot for immutable helpers // A spot for immutable helpers
namespace imm // TODO
// TODO
// TODO
// x) Wrap metadata into its own struct
namespace imm;
static public class Util
{ {
//This can handle both Timed and Recorded
static public T Process<T>( ref T obj, Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("fn")]
string expression = default )
where T : Recorded<T>
{
obj = obj.Process( fn, reason, memberName, filePath, lineNumber, expression );
return obj;
}
//This can handle both Timed and Recorded
static public T Versioned<T>( ref T obj, Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("fn")]
string expression = default )
where T : Versioned<T>
{
obj = obj.Process( fn, reason );
return obj;
}
}
public record class Versioned<T> public record class Versioned<T>
where T : Versioned<T> where T : Versioned<T>
{ {
public delegate void ChangeDelegate( T old, T next ); public delegate void ChangeDelegate( T ZZOld, T next );
public uint Version { get; protected set; } = 0; public record class MetaData
public string Reason { get; protected set; } = ""; {
public uint Version { get; internal set; } = 0;
public string Reason { get; internal set; } = "";
public MetaData() { }
}
internal Versioned( MetaData meta )
{
MetaStorage = meta;
}
internal MetaData MetaStorage = new();
public MetaData Meta => MetaStorage;
public ChangeDelegate OnChange; public ChangeDelegate OnChange;
@ -28,8 +77,11 @@ namespace imm
return newT with return newT with
{ {
Version = newT.Version + 1, MetaStorage = Meta with
{
Version = newT.Meta.Version + 1,
Reason = reason, Reason = reason,
}
}; };
} }
} }
@ -37,37 +89,48 @@ namespace imm
public record class Recorded<T> : Versioned<T> public record class Recorded<T> : Versioned<T>
where T : Recorded<T> where T : Recorded<T>
{ {
public T? Old { get; protected set; } new public record class MetaData : Versioned<T>.MetaData
public string Expression { get; protected set; } = ""; {
public string MemberName { get; protected set; } = ""; public T? ZZOld { get; internal set; }
public string FilePath { get; protected set; } = ""; public T? Old => ZZOld;
public int LineNumber { get; protected set; } = -1; public string Expression { get; internal set; } = "";
public string MemberName { get; internal set; } = "";
public string FilePath { get; internal set; } = "";
public int LineNumber { get; internal set; } = -1;
public T Record( string reason = "", public MetaData() { }
}
public Recorded() : this( new MetaData() )
{
}
public Recorded(MetaData meta) : base( meta )
{
}
new public MetaData Meta => MetaStorage as MetaData;
virtual public T Record( string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0 ) [CallerLineNumber] int lineNumber = 0 )
{ {
var orig = ( T )this; return Process( t => t, reason, memberName, filePath, lineNumber );
var next = ( T ) this with
{
//Do the Versioned code here
Version = orig.Version + 1,
Reason = reason,
Old = orig,
MemberName = memberName,
FilePath = filePath,
LineNumber = lineNumber,
};
OnChange( orig, next );
return next;
} }
public T Process( Func<T, T> fn, string reason = "", virtual public T Process( T next, string reason = "",
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("next")]
string expression = default )
{
return Process( ( old ) => next, reason, memberName, filePath, lineNumber, expression );
}
virtual public T Process( Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
@ -76,20 +139,21 @@ namespace imm
{ {
var orig = ( T )this; var orig = ( T )this;
var next = ( T )fn( orig ); var next = fn( orig );
var ret = ( T )next with var ret = next with
{ {
//Do the Versioned code here //Do the Versioned code here
Version = orig.Version + 1, MetaStorage = Meta with
{
Version = orig.Meta.Version + 1,
Reason = reason, Reason = reason,
//Recorded ZZOld = orig,
Old = orig,
Expression = expression,
MemberName = memberName, MemberName = memberName,
FilePath = filePath, FilePath = filePath,
LineNumber = lineNumber, LineNumber = lineNumber,
}
}; };
OnChange( orig, ret ); OnChange( orig, ret );
@ -101,12 +165,36 @@ namespace imm
public record class Timed<T> : Recorded<T> public record class Timed<T> : Recorded<T>
where T : Timed<T> where T : Timed<T>
{
new public record class MetaData : Recorded<T>.MetaData
{ {
public readonly DateTime CreatedAt = DateTime.Now; public readonly DateTime CreatedAt = DateTime.Now;
public DateTime TouchedAt { get; set; } = DateTime.Now; public DateTime TouchedAt { get; internal set; } = DateTime.Now;
}
public Timed() : this( new MetaData() )
{
}
public Timed( MetaData meta ) : base( meta )
{
}
new public MetaData Meta => MetaStorage as MetaData;
public TimeSpan Since => Meta.TouchedAt - Meta.Old?.Meta.TouchedAt ?? TimeSpan.MaxValue;
public T Process( T next, string reason = "", override public T Record( string reason = "",
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0 )
{
return Process( t => t, reason, memberName, filePath, lineNumber );
}
override public T Process( T next, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
@ -117,7 +205,7 @@ namespace imm
} }
new public T Process( Func<T, T> fn, string reason = "", override public T Process( Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
@ -126,38 +214,32 @@ namespace imm
{ {
var orig = ( T )this; var orig = ( T )this;
var next = ( T )fn( orig ); var next = fn( orig );
var ret = ( T )next with var ret = next with
{
MetaStorage = Meta with
{ {
//Versioned //Versioned
Version = orig.Version + 1, Version = orig.Meta.Version + 1,
Reason = reason, Reason = reason,
//Recorded //Recorded
Old = orig,
Expression = expression,
MemberName = memberName, MemberName = memberName,
FilePath = filePath, FilePath = filePath,
LineNumber = lineNumber, LineNumber = lineNumber,
ZZOld = orig,
//Timed //Timed
TouchedAt = DateTime.Now, TouchedAt = DateTime.Now,
}
}; };
OnChange( orig, ret ); if( OnChange != null) OnChange( orig, ret );
return ret; return ret;
} }
}
public static class Util
{
} }
}

View File

@ -34,6 +34,8 @@ static public class log
Invalid = 0, Invalid = 0,
File = 1 << 0, File = 1 << 0,
Console = 1 << 1, Console = 1 << 1,
All = File | Console,
} }

View File

@ -88,9 +88,9 @@ namespace lib
public class XmlFormatter2Cfg: Config public class XmlFormatter2Cfg: Config
{ {
public readonly Datastructure datastructure = Datastructure.Graph; public Datastructure datastructure = Datastructure.Graph;
public readonly int Version = 2; public int Version = 2;
} }
public class XmlFormatter2: IFormatter public class XmlFormatter2: IFormatter