diff --git a/SharpLib.csproj b/SharpLib.csproj index 3c65003..9926905 100644 --- a/SharpLib.csproj +++ b/SharpLib.csproj @@ -1,7 +1,7 @@ - net9.0;net8.0;net10.0 + net9.0;net10.0 lib 0.0.1.0 0.0.1.0 diff --git a/exp/Exp.cs b/exp/Exp.cs index 6b785cd..6a58bab 100644 --- a/exp/Exp.cs +++ b/exp/Exp.cs @@ -1,7 +1,6 @@ using System.Collections.Immutable; using System.Runtime.CompilerServices; - namespace exp; diff --git a/imm/FSM.cs b/imm/FSM.cs index f581999..3f066bf 100644 --- a/imm/FSM.cs +++ b/imm/FSM.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Runtime.CompilerServices; @@ -12,7 +12,7 @@ public abstract record class FsmContextBase : io.Recorded where TSelf : FsmContextBase { // Required for 'with' expressions. - protected FsmContextBase( io.Recorded original ) : base( original ) { } + protected FsmContextBase(io.Recorded original) : base(original) { } protected FsmContextBase() { } } @@ -29,7 +29,7 @@ public abstract record class FsmStateBase : io.Recorded /// /// Called when entering this state. /// - public virtual (TCtx Context, TSelf State) OnEnter( TCtx context, FsmStateBase oldState ) + public virtual (TCtx Context, TSelf State) OnEnter(TCtx context, FsmStateBase oldState) { return (context, (TSelf)this); } @@ -37,13 +37,13 @@ public abstract record class FsmStateBase : io.Recorded /// /// Called when exiting this state. /// - public virtual (TCtx Context, TSelf State) OnExit( TCtx context, FsmStateBase newState ) + public virtual (TCtx Context, TSelf State) OnExit(TCtx context, FsmStateBase newState) { return (context, (TSelf)this); } // Required for 'with' expressions. - protected FsmStateBase( io.Recorded original ) : base( original ) { } + protected FsmStateBase(io.Recorded original) : base(original) { } protected FsmStateBase() { } } @@ -62,14 +62,14 @@ public abstract record class FsmBase : io.Recorded public TCtx Context { get; init; } public TState State { get; init; } - protected FsmBase( TCtx initialContext, TState initialState ) + protected FsmBase(TCtx initialContext, TState initialState) { Context = initialContext; State = initialState; } // Required for 'with' expressions. - protected FsmBase( io.Recorded original ) : base( original ) + protected FsmBase(io.Recorded original) : base(original) { var o = original as FsmBase; Context = o!.Context; @@ -78,7 +78,7 @@ public abstract record class FsmBase : io.Recorded /// /// Transitions the FSM. It automatically uses the 'Process' - /// method appropriate for io.ecorded or Timed, thanks to virtual overrides. + /// method appropriate for io.Recorded or Timed, thanks to virtual overrides. /// public TSelf Transition( TState newState, @@ -86,12 +86,12 @@ public abstract record class FsmBase : io.Recorded [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0, - [CallerArgumentExpression( "newState" )] string expression = "" ) + [CallerArgumentExpression("newState")] string expression = "") { - Console.WriteLine( $"[FSM] Transition: {State.GetType().Name} -> {newState.GetType().Name}. Reason: {reason}" ); + Console.WriteLine($"[FSM] Transition: {State.GetType().Name} -> {newState.GetType().Name}. Reason: {reason}"); - var (ctxAfterExit, stateAfterExit) = State.OnExit( Context, newState ); - var (ctxAfterEnter, stateAfterEnter) = newState.OnEnter( ctxAfterExit, stateAfterExit ); + var (ctxAfterExit, stateAfterExit) = State.OnExit(Context, newState); + var (ctxAfterEnter, stateAfterEnter) = newState.OnEnter(ctxAfterExit, stateAfterExit); // Since 'this' is at least 'io.Recorded', we can call the // detailed 'Process'. If 'this' is actually 'Timed', C#'s diff --git a/imm/Imm.cs b/imm/Imm.cs index 29411df..5fc8745 100644 --- a/imm/Imm.cs +++ b/imm/Imm.cs @@ -1,9 +1,8 @@ -//#nullable enable +//#nullable enable using System; using System.Runtime.CompilerServices; - /// /// Helper static class for processing immutable objects using a 'ref' pattern. /// Provides different levels of processing based on the type. @@ -16,8 +15,8 @@ public static class imm public static T LightProcess( ref T obj, Func fn, - string reason = "Processed" // TODO Replace the string with a $"" that cinludes some info - ) where T : io.Versioned + string reason = "Processed" ) + where T : io.Versioned { obj = obj.Process( fn, reason ); return obj; @@ -43,9 +42,9 @@ public static class imm } public static string LogDiff( T cur, T old, [CallerArgumentExpression( "cur" )] string dbgExpCur = "", [CallerArgumentExpression( "old" )] string dbgExpOld = "" ) - { + { return $"{dbgExpCur} changed from {old} to {cur}"; - } + } // No specific Process needed for Timed, as it's caught by Recorded // and its Process override handles the timing. diff --git a/imm/List.cs b/imm/List.cs index 4998130..70dae60 100644 --- a/imm/List.cs +++ b/imm/List.cs @@ -11,7 +11,7 @@ namespace io; /// /// An immutable list implementation that tracks history, metadata, and time. /// -public record class List : io.Timed>, IImmutableList +public record class List : Timed>, IImmutableList { static public List Empty { get; } = new(); @@ -19,7 +19,7 @@ public record class List : io.Timed>, IImmutableList public List() { } // Required for 'with' expressions to work with the base class hierarchy - protected List( io.Timed> original ) : base( original ) { } + protected List(Timed> original) : base(original) { } // Helper to apply changes using the Process method private List Change( @@ -29,54 +29,54 @@ public record class List : io.Timed>, IImmutableList [CallerLineNumber] int dbgLine = -1, [CallerArgumentExpression( "listChange" )] string reason = "" ) { - var newValues = listChange( Values ); - return ReferenceEquals( Values, newValues ) + var newValues = listChange(Values); + return ReferenceEquals(Values, newValues) ? this - : Process( l => l with { Values = newValues }, reason, dbgMethod, dbgPath, dbgLine, reason ); + : Process(l => l with { Values = newValues }, reason, dbgMethod, dbgPath, dbgLine, reason); } // --- IImmutableList implementation using the Change helper --- public T this[int index] => Values[index]; public int Count => Values.Count; - public List Add( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Add( value ), dbgMethod, dbgPath, dbgLine ); - public List AddRange( IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.AddRange( items ), dbgMethod, dbgPath, dbgLine ); - public List Clear( [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Clear(), dbgMethod, dbgPath, dbgLine ); + public List Add(T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.Add(value), dbgMethod, dbgPath, dbgLine); + public List AddRange(IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.AddRange(items), dbgMethod, dbgPath, dbgLine); + public List Clear([CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1) => Change(v => v.Clear(), dbgMethod, dbgPath, dbgLine); #region IImmutableList Implementati, dbgMethod, dbgPath, dbgLineon - public List Insert( int index, T element, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Insert( index, element ), dbgMethod, dbgPath, dbgLine ); - public List InsertRange( int index, IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.InsertRange( index, items ), dbgMethod, dbgPath, dbgLine ); - public List Remove( T value, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Remove( value, equalityComparer ), dbgMethod, dbgPath, dbgLine ); - public List Remove( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Remove( value, EqualityComparer.Default, dbgMethod, dbgPath, dbgLine ); - public List RemoveAll( Predicate match, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAll( match ), dbgMethod, dbgPath, dbgLine ); - public List RemoveAt( int index, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAt( index ), dbgMethod, dbgPath, dbgLine ); - public List RemoveRange( int index, int count, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( index, count ), dbgMethod, dbgPath, dbgLine ); - public List RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( items, equalityComparer ), dbgMethod, dbgPath, dbgLine ); - public List Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Replace( oldValue, newValue, equalityComparer ), dbgMethod, dbgPath, dbgLine ); - public List SetItem( int index, T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.SetItem( index, value ), dbgMethod, dbgPath, dbgLine ); + public List Insert( int index, T element, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Insert( index, element ) , dbgMethod, dbgPath, dbgLine); + public List InsertRange( int index, IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.InsertRange( index, items ) , dbgMethod, dbgPath, dbgLine); + public List Remove( T value, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Remove( value, equalityComparer ) , dbgMethod, dbgPath, dbgLine); + public List Remove( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Remove( value, EqualityComparer.Default , dbgMethod, dbgPath, dbgLine); + public List RemoveAll( Predicate match, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAll( match ) , dbgMethod, dbgPath, dbgLine); + public List RemoveAt( int index, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAt( index ) , dbgMethod, dbgPath, dbgLine); + public List RemoveRange( int index, int count, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( index, count ) , dbgMethod, dbgPath, dbgLine); + public List RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( items, equalityComparer ) , dbgMethod, dbgPath, dbgLine); + public List Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Replace( oldValue, newValue, equalityComparer ) , dbgMethod, dbgPath, dbgLine); + public List SetItem( int index, T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.SetItem( index, value ) , dbgMethod, dbgPath, dbgLine); public int IndexOf( T item, int index, int count, IEqualityComparer? equalityComparer ) => Values.IndexOf( item, index, count, equalityComparer ?? EqualityComparer.Default ); - public int LastIndexOf( T item, int index, int count, IEqualityComparer? equalityComparer ) => Values.LastIndexOf( item, index, count, equalityComparer ?? EqualityComparer.Default ); + public int LastIndexOf( T item, int index, int count, IEqualityComparer? equalityComparer) => Values.LastIndexOf( item, index, count, equalityComparer ?? EqualityComparer.Default ); - public int IndexOf( T item, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => IndexOf( item, 0, Count, EqualityComparer.Default ); + public int IndexOf( T item, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => IndexOf( item, 0, Count, EqualityComparer.Default); IImmutableList IImmutableList.Clear() => Clear(); - IImmutableList IImmutableList.Add( T value ) => Add( value ); - IImmutableList IImmutableList.AddRange( IEnumerable items ) => AddRange( items ); - IImmutableList IImmutableList.Insert( int index, T element ) => Insert( index, element ); - IImmutableList IImmutableList.InsertRange( int index, IEnumerable items ) => InsertRange( index, items ); - IImmutableList IImmutableList.Remove( T value, IEqualityComparer? equalityComparer ) => Remove( value, equalityComparer ); - IImmutableList IImmutableList.RemoveAll( Predicate match ) => RemoveAll( match ); - IImmutableList IImmutableList.RemoveAt( int index ) => RemoveAt( index ); - IImmutableList IImmutableList.RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer ) => RemoveRange( items, equalityComparer ); - IImmutableList IImmutableList.RemoveRange( int index, int count ) => RemoveRange( index, count ); - IImmutableList IImmutableList.Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer ) => Replace( oldValue, newValue, equalityComparer ); - IImmutableList IImmutableList.SetItem( int index, T value ) => SetItem( index, value ); + IImmutableList IImmutableList.Add( T value ) => Add( value ); + IImmutableList IImmutableList.AddRange( IEnumerable items ) => AddRange( items ); + IImmutableList IImmutableList.Insert( int index, T element ) => Insert( index, element ); + IImmutableList IImmutableList.InsertRange( int index, IEnumerable items ) => InsertRange( index, items ); + IImmutableList IImmutableList.Remove( T value, IEqualityComparer? equalityComparer ) => Remove( value, equalityComparer ); + IImmutableList IImmutableList.RemoveAll( Predicate match ) => RemoveAll( match ); + IImmutableList IImmutableList.RemoveAt( int index ) => RemoveAt( index ); + IImmutableList IImmutableList.RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer ) => RemoveRange( items, equalityComparer ); + IImmutableList IImmutableList.RemoveRange( int index, int count ) => RemoveRange( index, count ); + IImmutableList IImmutableList.Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer ) => Replace( oldValue, newValue, equalityComparer ); + IImmutableList IImmutableList.SetItem( int index, T value ) => SetItem( index, value ); #endregion // --- Standard Interfaces --- public IEnumerator GetEnumerator() => Values.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => ( (IEnumerable)Values ).GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)Values).GetEnumerator(); } diff --git a/imm/Util.cs b/imm/Util.cs index 52991ff..585827a 100644 --- a/imm/Util.cs +++ b/imm/Util.cs @@ -1,3 +1,2 @@ using System; using System.Collections.Generic; - diff --git a/imm/io.cs b/imm/io.cs index 59839e1..840d319 100644 --- a/imm/io.cs +++ b/imm/io.cs @@ -23,7 +23,7 @@ public interface Obj /// Gets the previous version as a base object, if available. /// Returns null if this is the first version or if history is not tracked. /// - Obj? DebugOld { get; } + Obj? Old { get; } /// /// Creates a new version without functional change. @@ -174,11 +174,11 @@ public record class Versioned : Obj where T : Versioned [JsonIgnore] public ChangeDelegate OnChange { get; set; } = ( o, n ) => { }; - public virtual Obj? DebugOld => null; + public virtual Obj? Old => null; Metadata_Versioned Obj.Meta => this.Meta; [JsonIgnore] - Obj? Obj.DebugOld => this.DebugOld; + Obj? Obj.Old => this.Old; public Versioned() { } protected Versioned( Versioned original ) @@ -239,9 +239,9 @@ public record class Recorded : Versioned where T : Recorded new public Metadata_Recorded Meta { get; init; } = new(); [JsonIgnore] - new public T? DebugOld => Meta.OldObject as T; + new public T? Old => Meta.OldObject as T; - //public override Obj? DebugOld => this.DebugOld; + //public override Obj? Old => this.Old; //Metadata_Versioned Obj.Meta => this.Meta; public Recorded() { } @@ -261,8 +261,7 @@ public record class Recorded : Versioned where T : Recorded if( ReferenceEquals( current, next ) ) return current; - var newMeta = current.Meta with - { + var newMeta = current.Meta with { Version = current.Meta.Version + 1, Reason = reason, MemberName = dbgName, @@ -295,7 +294,7 @@ public record class Timed : Recorded where T : Timed { new public Metadata_Timed Meta { get; init; } = new(); //Metadata_Versioned Obj.Meta => this.Meta; - public TimeSpan SinceLastTouch => Meta.TouchedAt - ( DebugOld?.Meta as Metadata_Timed )?.TouchedAt ?? TimeSpan.Zero; + public TimeSpan SinceLastTouch => Meta.TouchedAt - ( Old?.Meta as Metadata_Timed )?.TouchedAt ?? TimeSpan.Zero; public TimeSpan TotalAge => Meta.TouchedAt - Meta.CreatedAt; public Timed() { } diff --git a/lib/XmlFormatter2.cs b/lib/XmlFormatter2.cs index cfe633e..715f1be 100644 --- a/lib/XmlFormatter2.cs +++ b/lib/XmlFormatter2.cs @@ -139,7 +139,7 @@ namespace lib private string fromStr = ""; - void SetFromStr( Stream stream ) + void SetFromStr( Stream stream ) { fromStr = stream.ToString() ?? "{null}"; @@ -186,8 +186,7 @@ namespace lib doc.Load( reader ); - if( doc.DocumentElement == null ) - return null; + if( doc.DocumentElement == null ) return null; if( t == null ) return Deserialize( doc.DocumentElement ); @@ -257,8 +256,7 @@ namespace lib { TypeCode typeCode = Type.GetTypeCode( type ); - if( _cfg.VerboseLogging ) - log.info( $"{type.FriendlyName()}.{name} {existing} {mi?.Name}" ); + if( _cfg.VerboseLogging ) log.info( $"{type.FriendlyName()}.{name} {existing} {mi?.Name}" ); if( typeCode != TypeCode.Object ) { @@ -278,8 +276,7 @@ namespace lib if( obj is ser.I_Serialize iser ) { - if( _cfg.VerboseLogging ) - log.info( $"" ); + if( _cfg.VerboseLogging ) log.info( $"" ); obj = iser.OnDeserialize( null ); } @@ -317,8 +314,7 @@ namespace lib private object DeserializeConcrete( XmlElement elem, MemberInfo mi, string name, Type type ) { - if( _cfg.VerboseLogging ) - log.info( $"" ); + if( _cfg.VerboseLogging ) log.info( $"" ); string val = ""; @@ -402,8 +398,7 @@ namespace lib private object HydrateObject( XmlElement elem, MemberInfo mi, Type finalType, object obj ) { - if( _cfg.VerboseLogging ) - log.info( $"" ); + if( _cfg.VerboseLogging ) log.info( $"" ); if( obj is IList ) { @@ -493,10 +488,9 @@ namespace lib private object HydrateObjectOfNarrowType( XmlElement elem, MemberInfo mi, Type narrowType, object obj ) { - if( _cfg.VerboseLogging ) - log.info( $"" ); + if( _cfg.VerboseLogging ) log.info( $"" ); - var isImm = typeof( io.Obj ).IsAssignableFrom( narrowType ); + var isImm = typeof(io.Obj).IsAssignableFrom( narrowType ); XmlNodeList allChildren = elem.ChildNodes; @@ -542,7 +536,7 @@ namespace lib name = refl.TypeToIdentifier( name ); // @@@ TODO This doesnt yet handle propNames! - if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) ) + if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) ) continue; var useFieldName = true; @@ -631,7 +625,7 @@ namespace lib { object existingObj = childPi.GetValue( obj ); - object childObj = DeserializeConcrete( elem, childPi, name, childPi.PropertyType ); + object childObj = DeserializeConcrete( elem, childPi, name, childPi.PropertyType ); if( setMethod != null ) { @@ -648,14 +642,14 @@ namespace lib } } - if( !isImm ) + if(!isImm) { return obj; } else { - var imm = obj as io.Obj; - var newObj = imm.Record( $"From XML {fromStr}:{elem.ParentNode?.Name}{elem.Name}" ); + var immObj = obj as io.Obj; + var newObj = immObj.Record( $"From XML {fromStr}:{elem.ParentNode?.Name}{elem.Name}" ); return newObj; } @@ -692,8 +686,7 @@ namespace lib int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1; - if( _cfg.VerboseLogging ) - log.info( $"{finalType?.FriendlyName()}({type?.FriendlyName()}) refInt {refInt} exitingObj = {obj?.ToString()}" ); + if( _cfg.VerboseLogging ) log.info( $"{finalType?.FriendlyName()}({type?.FriendlyName()}) refInt {refInt} exitingObj = {obj?.ToString()}" ); obj = createObject( elem, finalType, refInt, obj ); @@ -702,8 +695,7 @@ namespace lib private object DeserializeList( XmlElement elem, MemberInfo mi, Type type, IList list ) { - if( _cfg.VerboseLogging ) - log.info( $"" ); + if( _cfg.VerboseLogging ) log.info( $"" ); XmlNodeList arrNodeList = elem.ChildNodes; @@ -739,8 +731,7 @@ namespace lib typeElem = typeof( KeyValuePair<,> ).MakeGenericType( type.GenericTypeArguments ); } - if( _cfg.VerboseLogging ) - log.info( $"DserCol {type.GetType().FriendlyName()} {typeElem.Name} into reflT {mi.ReflectedType.FriendlyName()} declT {mi.DeclaringType.FriendlyName()} {mi.Name}" ); + if( _cfg.VerboseLogging ) log.info( $"DserCol {type.GetType().FriendlyName()} {typeElem.Name} into reflT {mi.ReflectedType.FriendlyName()} declT {mi.DeclaringType.FriendlyName()} {mi.Name}" ); string refString = elem.GetAttribute( "ref" ); int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1; @@ -785,8 +776,7 @@ namespace lib var typeGen = Type.MakeGenericSignatureType( type ); - if( _cfg.VerboseLogging ) - log.info( $"TypeGen: {typeGen.FriendlyName()}" ); + if( _cfg.VerboseLogging ) log.info( $"TypeGen: {typeGen.FriendlyName()}" ); if( type == typeof( ImmutableArray<> ).MakeGenericType( typeElem ) ) { @@ -843,8 +833,7 @@ namespace lib private object DeserializeArray( XmlElement elem, MemberInfo mi, Type type ) { - if( _cfg.VerboseLogging ) - log.info( $"" ); + if( _cfg.VerboseLogging ) log.info( $"" ); Type typeElem = type.GetElementType(); @@ -894,8 +883,7 @@ namespace lib if( _cfg.datastructure == Datastructure.Graph && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) { - if( _cfg.VerboseLogging ) - log.info( $"Reuse object" ); + if( _cfg.VerboseLogging ) log.info( $"Reuse object" ); return m_alreadySerialized[refInt]; } @@ -905,8 +893,7 @@ namespace lib if( isProxy ) { - if( _cfg.VerboseLogging ) - log.info( $"use Proxy" ); + if( _cfg.VerboseLogging ) log.info( $"use Proxy" ); object obj = null; var tryType = type; @@ -950,8 +937,7 @@ namespace lib if( isSubclass ) { - if( _cfg.VerboseLogging ) - log.info( $"Using existing obj {existingObj?.ToString()}" ); + if( _cfg.VerboseLogging ) log.info( $"Using existing obj {existingObj?.ToString()}" ); return existingObj; } @@ -967,14 +953,12 @@ namespace lib try { - if( _cfg.VerboseLogging ) - log.info( $"For {type.FriendlyName()} check for constructors" ); + if( _cfg.VerboseLogging ) log.info( $"For {type.FriendlyName()} check for constructors" ); var cons = type.GetConstructor( Type.EmptyTypes ); - if( cons != null ) + if( cons != null) { - if( _cfg.VerboseLogging ) - log.info( $"Activator.CreateInstance" ); + if( _cfg.VerboseLogging ) log.info( $"Activator.CreateInstance" ); obj = Activator.CreateInstance( type ); } else @@ -983,18 +967,15 @@ namespace lib obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type ); } - if( _cfg.VerboseLogging ) - log.info( $"Got obj {obj?.ToString()}" ); + if( _cfg.VerboseLogging ) log.info( $"Got obj {obj?.ToString()}" ); } catch( Exception ) { try { - if( _cfg.VerboseLogging ) - log.info( $"GetUninitializedObject" ); + if( _cfg.VerboseLogging ) log.info( $"GetUninitializedObject" ); obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type ); - if( _cfg.VerboseLogging ) - log.info( $"Got obj {obj?.ToString()}" ); + if( _cfg.VerboseLogging ) log.info( $"Got obj {obj?.ToString()}" ); } catch( Exception exInner ) { @@ -1309,7 +1290,7 @@ namespace lib HashSet whitelistFields, whitelistProps; GetFilters( _cfg.TypesDefault, mi, narrowType, out filterFields, out filterProps, out doImpls, out doFields, out doProps, out whitelistFields, out whitelistProps ); - var isImm = typeof( io.Obj ).IsAssignableFrom( narrowType ); + var isImm = typeof(io.Obj).IsAssignableFrom( narrowType ); if( doFields || doImpls ) { @@ -1342,10 +1323,8 @@ namespace lib if( isImm ) { - if( name == "MetaStorage" ) - continue; - if( name == "Fn" ) - continue; + if( name == "MetaStorage" ) continue; + if( name == "Fn" ) continue; } if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) ) @@ -1386,10 +1365,8 @@ namespace lib if( isImm ) { - if( name == "MetaStorage" ) - continue; - if( name == "Fn" ) - continue; + if( name == "MetaStorage" ) continue; + if( name == "Fn" ) continue; } if( FilterField( filterProps, doImpls, whitelistProps, childPi as MemberInfo, name ) ) @@ -1416,15 +1393,15 @@ namespace lib var custWLProps = mi?.GetCustomAttribute( true ); filterFields = custWLFields != null; - filterProps = custWLProps != null; + filterProps = custWLProps != null; var typesTodo = type.GetCustomAttribute( true )?.Types ?? TypesDefault; - doImpls = typesTodo.HasFlag( ser.Types.Implied ); + doImpls = typesTodo.HasFlag( ser.Types.Implied ); doFields = filterFields || typesTodo.HasFlag( ser.Types.Fields ); - doProps = filterProps || typesTodo.HasFlag( ser.Types.Props ); + doProps = filterProps || typesTodo.HasFlag( ser.Types.Props ); whitelistFields = new( custWLFields?.Values ?? new string[0] ); - whitelistProps = new( custWLProps?.Values ?? new string[0] ); + whitelistProps = new( custWLProps?.Values ?? new string[0] ); } private void SerializeArray( XmlWriter writer, MemberInfo mi, Type mType, object root, int depth ) @@ -1436,10 +1413,8 @@ namespace lib Type type = root.GetType(); Type typeOfMember = typeof( object ); - if( mi is FieldInfo fi ) - typeOfMember = fi.FieldType; - if( mi is PropertyInfo pi ) - typeOfMember = pi.PropertyType; + if( mi is FieldInfo fi ) typeOfMember = fi.FieldType; + if( mi is PropertyInfo pi ) typeOfMember = pi.PropertyType; if( typeOfMember != type ) { log.info( $"SerArr {typeOfMember.FriendlyName()} {mi?.Name} != {type.FriendlyName()}" ); diff --git a/logging/Log.cs b/logging/Log.cs index 5d588fb..4dc67e9 100644 --- a/logging/Log.cs +++ b/logging/Log.cs @@ -18,10 +18,10 @@ using System.Text; /* T O D O : +x) Hook the C# prints from glue. +x) Fix x) Refactor various logs in order to do automagic structured logging ref: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler -x) Add support for structured logging (e.g., JSON, XML) -x) Implement a centralized logger that can be used across the application D O N E: @@ -32,63 +32,7 @@ N O T  D O I N G : */ - -/* -// L L M -# Context: Logging Infrastructure (`log` static class) -**Strict Rule:** DO NOT use `Console.WriteLine`, `Debug.WriteLine`, or standard `ILogger`. Use the static `log` class for all diagnostics. - -## Core Design Pattern -The logging system uses **Caller Info Attributes** (`[CallerMemberName]`, `[CallerFilePath]`, etc.) to automatically capture context. Do not manually format method names or file paths in messages. - -## API Surface -### 1. Standard Levels. Standard goto loggin -* `log.trace(msg)`, `log.debug(msg)`, `log.info(msg)` -* `log.warn(msg)`, `log.high(msg)` -* `log.error(msg)`, `log.fatal(msg)` -* **Signature:** `(string msg, string cat = "", SourceLoc? loc = null)` -* *Note:* `cat` (Category) and `loc` (SourceLocation) are optional; the system auto-resolves `cat` based on directory structure if omitted. - -### 2. Functional Pass-Throughs If necessary -Use these to log data flow without breaking the statement chain. -* `T log.var(T val)`: Logs `name_of_var = value` and returns `val`. -* `T log.call(Func func)`: Logs entry, executes `func`, logs exit + result, returns result. -* `void log.call(Action func)`: Logs entry, executes `action`, logs exit. -* `log.operations(Action/Func)`: Wraps execution with info logs. - -### 3. Special Types -* `Value`: A struct wrapper to capture variable expressions alongside values. Use `log.Value(var)` when you need explicit expression capturing in custom constructs. -* `log.exception(Exception ex, string msg)`: specialized dump for exceptions. -* `log.logProps(object obj, string header)`: Reflection-based dump of all properties on an object. - -## Idiomatic Usage Examples -**Good:** -```csharp -// Variable inspection (Pass-through) -int x = log.var(Calculate()); - -// Function tracing -var result = log.call(() => ComplexCalculation(input)); - -// Exception handling -try { ... } -catch (Exception ex) { log.exception(ex, "Calculation failed"); } - -// Object Dump -log.logProps(userConfig, "Current Config State"); -``` - -**Bad:** -```csharp -int x = Calculate(); -Console.WriteLine("x is " + x); // Forbidden -log.info($"x = {x}"); // Redundant manual formatting -``` - - -*/ - - +#region Helpers public record struct Value( T _val, string _exp = "" ) { public static T Default = default!; @@ -144,13 +88,10 @@ public struct SourceLoc } - +#endregion // Helpers static public class log { - - //static - #region CLR Logging @@ -212,14 +153,6 @@ static public class log #endregion // CLR Logging - static public Value Value( T val, - [CallerArgumentExpression("val")] - string dbgExp = "" -) - { - return new( val, dbgExp ); - } - [Flags] public enum LogType { @@ -241,13 +174,15 @@ static public class log { None = 0, - File = 1 << 0, + File = 1 << 0, Console = 1 << 1, All = File | Console, } - #region LogEvent + +#region LogEvent + public struct LogEvent { public DateTime Time; @@ -311,7 +246,6 @@ static public class log return logEvent; } - #endregion // LogEvent public delegate void Log_delegate( LogEvent evt ); @@ -322,7 +256,7 @@ static public class log ImmutableInterlocked.AddOrUpdate( ref s_logEPforCat, cat, ep, ( k, v ) => ep ); } - +#endregion // LogEvent static public void shutdown() { @@ -365,7 +299,7 @@ static public class log pathPieces = path.Split( '/' ); } - var lastPathPiece = pathPieces[pathPieces.Length - 1]; + var lastPathPiece = pathPieces[pathPieces.Length - 1]; ImmutableInterlocked.AddOrUpdate( ref s_files, pathHash, lastPathPiece, ( key, value ) => { return lastPathPiece; } ); @@ -462,32 +396,32 @@ static public class log } [StackTraceHidden] - static public void info( string msg, string cat = "", SourceLoc? loc = null, + static public void info( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) { logBase( msg, LogType.Info, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc ); } [StackTraceHidden] - static public void debug( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) + static public void debug( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) { logBase( msg, LogType.Debug, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc ); } [StackTraceHidden] - static public void trace( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) + static public void trace( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) { logBase( msg, LogType.Trace, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc ); } [StackTraceHidden] - static public void warn( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) + static public void warn( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) { logBase( msg, LogType.Warn, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc ); } [StackTraceHidden] - static public void high( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) + static public void high( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) { logBase( msg, LogType.High, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc ); } @@ -522,12 +456,12 @@ static public class log [StackTraceHidden] - static public void fatal( string msg, string cat = "", SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) + static public void fatal( string msg, string cat = "",SourceLoc? loc = null, [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerMemberName] string dbgMethod = "", [CallerArgumentExpression( "msg" )] string dbgExp = "" ) { logBase( msg, LogType.Fatal, dbgPath, dbgLine, dbgMethod, cat, dbgExp, loc ); } - //new LogEvent( LogType.Raw, $"", "", 0, "", "lib.time", "", null ) +//new LogEvent( LogType.Raw, $"", "", 0, "", "lib.time", "", null ) #endregion @@ -589,7 +523,7 @@ static public class log foreach( var fr in stackTrace.GetFrames() ) { - logBase( $"{fr.Log}", LogType.Raw ); + logBase( $"{fr.Log}", LogType.Raw ); } } @@ -612,14 +546,14 @@ static public class log } - static public LogEvent logCreateEvent( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "", SourceLoc? loc = null ) + static public LogEvent logCreateEvent( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "",SourceLoc? loc = null ) { LogEvent evt = new LogEvent( type, msg, dbgPath, dbgLine, dbgMethod, cat, exp, loc ); return evt; } [StackTraceHidden] - static public void logBase( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "", SourceLoc? loc = null ) + static public void logBase( string msg, LogType type = LogType.Debug, string dbgPath = "", int dbgLine = -1, string dbgMethod = "", string cat = "unk", string exp = "",SourceLoc? loc = null ) { var evt = logCreateEvent( msg, type, dbgPath, dbgLine, dbgMethod, cat, exp ); @@ -1078,4 +1012,13 @@ static public class log private static ArrayList s_delegates = new ArrayList(); -} + static public Value Value( T val, + [CallerArgumentExpression("val")] + string dbgExp = "" +) + { + return new( val, dbgExp ); + } + + +} // end static class log diff --git a/res/Resource.cs b/res/Resource.cs index b35c292..2ceb0c5 100644 --- a/res/Resource.cs +++ b/res/Resource.cs @@ -182,7 +182,7 @@ public class Ref : Ref where T : class, new() // Let's assume you'll add saving logic here. // Mgr.Save(value, path); // Example: Needs implementation - var immMeta = ( value as io.Obj )?.Meta; + var immMeta = (value as io.Obj)?.Meta; @@ -433,7 +433,7 @@ public static class Mgr var loadedObject = loaderHolder.Load( filename, reason, dbgName, dbgPath, dbgLine ); if( loadedObject is T value ) { - var meta = ( value as io.Obj )?.Meta; + var meta = (value as io.Obj)?.Meta; // If it's an immutable object, record its loading. if( value is io.Obj imm )